filein (RsConfigGetWildWestDir() + "script/3dsmax/_config_files/wildwest_header.ms") struct FXEntity ( meshName, DiffuseTextures, meshXForm, interior ) struct interiorLocation ( interiorType, location, position, heading ) struct FXTestExporterStruct ( interiors = #(), interiorsUI = #(), interiorsConfig = (RsConfigGetToolsDir() + "etc/config/generic/gameLauncher.ini"), interiorPositions = (RsConfigGetWildwestDir() + "etc/config/general/interiorsMaxPositions.ini"), interiorMaxPositions = #(), fxPositionsXML = (RsConfigGetBuildDir() + "common/data/effects/bink/vfxPositions.xml"), fxPositions = #(), meshes = #(), rolloutUI, selectedInterior, interiorMaxPos, interiorPos, interiorHeading, allTextures = #(), txMetaDataPath = @"X:\gta5\assets_ng\metadata\textures\maps\*.tcs", txTCSList = #(), locations = #(), locationXMLPath = (RsConfigGetBuildDir() + "common/data/script/xml/InteriorLocationInfo/InteriorsInfo.XML"), regex = dotnetclass "System.Text.RegularExpressions.Regex", re_IgnoreCase = (dotnetclass "System.Text.RegularExpressions.RegexOptions").IgnoreCase, /* fn get_Interiors = ( --use the gamelauncher interiors config to get a list of interiors for the array and thier world space positions interiorItems = getINISetting interiorsConfig "Interior" for item in interiorItems do ( --interiorName = getINISetting interiorsConfig p = filterString (getINISetting interiorsConfig "Interior" item) " " position = [p[1] as float, p[2] as float, p[3] as float] append interiors (DataPair name:item position:position) append interiorsUI item ) ), */ fn get_InteriorsMaxPositions = ( print "getting max positions" interiorINI = try (getINISetting interiorPositions "Interior") catch(messageBox ("Unable to load " + RsConfigGetWildwestDir() + "etc/config/general/interiorsMaxPositions.ini")) for item in interiorINI do ( p = filterString (getINISetting interiorPositions "Interior" item) " " position = [p[1] as float, p[2] as float, p[3] as float] append interiorMaxPositions (DataPair name:item position:position) ) --break() --print interiorMaxPositions ), fn get_Locations = ( format "Getting Locations.." xmlStream = xmlStreamHandler xmlFile:locationXMLPath --try --( xmlStream.open() --get me some interior locations root = xmlStream.root items = root.GetElementsByTagName "Item" --print items itemIt = items.GetEnumerator() --for loc in items do while itemIt.MoveNext() do ( loc = itemIt.current --print "." --create an interioLocation interiorLoc = interiorLocation() --interiorLoc.location = (regex.match loc.childNodes.item[0].innerText ".+(?=(_interior.+))").value interiorLoc.location = loc.childNodes.item[0].innerText interiorLoc.interiorType = loc.childNodes.item[1].innerText posElem = loc.childNodes.item[2] posX = (posElem.GetAttribute "x") as Float posY = (posElem.GetAttribute "y") as Float posZ = (posElem.GetAttribute "z") as Float interiorLoc.position = [posX, posY, posZ] interiorLoc.heading = (loc.childNodes.item[3].GetAttribute "value") as Float --DataPair interior: items:#() --check if it already exist in the loaciton array existsAlready = false for l=1 to locations.count do ( if locations[l].interior == interiorLoc.interiorType then existsAlready = l ) --print existsAlready if existsAlready != false then ( --print locations[existsAlready] append locations[existsAlready].items interiorLoc ) else --else add ( append locations ( DataPair interior:interiorLoc.interiorType items:#(interiorLoc) ) ) ) xmlStream.close() --) --catch --( -- xmlStream.close() --) ), fn getShaderDiffuseTexture mat = ( textures = #() if classOf mat == Rage_Shader then ( textures = for v = 1 to RstGetVariableCount mat where RstGetVariableType mat v == "texmap" and \ findString (RstGetVariableName mat v) "Diffuse" != 0 and \ (RstGetVariable mat v) != "" \ collect (filterstring (pathConfig.stripPathToLeaf(RstGetVariable mat v)) ".")[1] ) return textures ), fn exportSelection = ( if $selection.count > 0 then ( meshes = #() --get the selection -filtering for meshes sel = for m in $selection where (superClassOf m) == GeometryClass collect m --foreach get its name and transform for m in sel do ( --create an FXEntity to store all the discovered goodies FXMesh = FXEntity() --name if matchPattern m.name pattern:"_RSref" then ( chopIdx = findstring m.name "_RSref" FXMesh.meshName = substring m.name 1 (chopIdx - 1) --FXMesh.meshName = substituteString m.name "_XREF" "" ) else ( FXMesh.meshName = m.name ) --mesh material - get the diffuse texture name textures = #() if m.material != undefined then ( --MultiSub or single case (classof m.material) of ( Multimaterial:textures = for sub = 1 to m.material.count collect (getShaderDiffuseTexture m.material[sub]) Rage_Shader:textures = getShaderDiffuseTexture m.material ) --Flatten array --flatTextures = #() --for i in textures where i.count != 0 do join flatTextures i --format "flatTextures: %\n" flatTextures FXMesh.DiffuseTextures = textures --add to the total set append allTextures textures ) --get chosen interior selectedInterior = tolower rolloutUI.ddlInteriors.selected selectedLocation = tolower rolloutUI.ddlLocations.selected --get its position interiorMaxPos = (for i in interiorMaxPositions where (tolower i.name) == selectedInterior collect i.position)[1] --get its game position theInterior = (for item in locations where item.interior == selectedInterior collect item)[1] theLocation = (for item in theInterior.items where item.location == selectedLocation collect item)[1] interiorPos = theLocation.position interiorHeading = theLocation.heading --get position adjusted by heading --zRot = rotateZMatrix theLocation.heading --get the mesh xform --rememberPos = m.position -- m.position = [0, 0, 0] -- FXMesh.meshXForm = m.transform * zRot -- m.position = rememberPos FXMesh.meshXForm = m.transform append meshes FXMesh ) return true ) else ( messagebox "No meshes selected" error:"No Selection" return false ) ), fn writeBinkXML = ( --create the document local xmlDoc = XmlDocument() xmlDoc.init() --create the root node local root = xmlDoc.createElement "MovieMeshInfoList" appendTo:xmlDoc.document local data = xmlDoc.createElement "Data" appendto:root --foreach fxPosition get its name and position for m in meshes do ( --create a node for the objects position and add the data item = xmlDoc.createElement "Item" appendto:data attrs:#(#("type", "MovieMeshInfo")) --meshname modelName = xmlDoc.createElement "ModelName" appendto:item modelName.InnerText = m.meshName --textures if m.DiffuseTextures == undefined then ( texture = xmlDoc.createElement "TextureName" appendto:item texture.InnerText = "" ) else if m.DiffuseTextures.count > 0 then ( for t = 1 to m.DiffuseTextures.count do ( texture = xmlDoc.createElement "TextureName" appendto:item texture.InnerText = m.DiffuseTextures[t] ) ) --transform transA = xmlDoc.createElement "TransformA" appendto:item attrs:#(#("x", m.meshXForm[1].x), #("y", m.meshXForm[1].y), #("z", m.meshXForm[1].z)) transB = xmlDoc.createElement "TransformB" appendto:item attrs:#(#("x", m.meshXForm[2].x), #("y", m.meshXForm[2].y), #("z", m.meshXForm[2].z)) transC = xmlDoc.createElement "TransformC" appendto:item attrs:#(#("x", m.meshXForm[3].x), #("y", m.meshXForm[3].y), #("z", m.meshXForm[3].z)) transD = xmlDoc.createElement "TransformD" appendto:item attrs:#(#("x", m.meshXForm[4].x), #("y", m.meshXForm[4].y), #("z", m.meshXForm[4].z)) ) --set the interior interiorName = xmlDoc.createElement "InteriorName" appendto:root interiorName.InnerText = selectedInterior interiorMaxPosElem = xmlDoc.createElement "InteriorMaxPosition" appendTo:root attrs:#(#("x", interiorMaxPos.x), #("y", interiorMaxPos.y), #("z", interiorMaxPos.z)) interiorPosElem = xmlDoc.createElement "InteriorPosition" appendTo:root attrs:#(#("x", interiorPos.x), #("y", interiorPos.y), #("z", interiorPos.z)) useInterior = xmlDoc.createElement "UseInterior" appendTo:root attrs:#(#("value", "true")) --write out bounding spheres boundingSpheres = xmlDoc.createElement "BoundingSpheres" appendto:root for obj in $objects where classof obj == GeoSphere and obj.isHidden == false and matchPattern obj.name pattern:"BS_*" == true do ( pos = obj.position radius = obj.radius xmlDoc.createElement "BoundingSphere" appendTo:boundingSpheres attrs:#(#("x", pos.x), #("y", pos.y), #("z", pos.z), #("radius", radius)) ) --write out the xml file try ( --get filename to out outFile = getSaveFileName caption:"VFX Test Export" filename:fxPositionsXML types:"Data(*.xml)|*.xml" if outFile != undefined then ( xmlDoc.save outFile ) ) catch ( messageBox "Could not save file, do you have it checked out?" title:"Fail!" return false ) --close file --user message messageBox "Export Finished!" title:"win!" ), fn writeLocationsXML = ( --create the document local xmlDoc = XmlDocument() xmlDoc.init() --create the root node local root = xmlDoc.createElement "MovieMeshInfoList" appendTo:xmlDoc.document --foreach fxPosition get its name and position for m in meshes do ( --create a node for the objects position and add the data --set the interior interiorName = xmlDoc.createElement "InteriorName" appendto:root attrs:#(#("name", selectedInterior)) --RoomName modelName = xmlDoc.createElement "RoomName" appendto:interiorName attrs:#(#("name", m.meshName)) interiorPosElem = xmlDoc.createElement "InteriorPosition" appendTo:interiorName attrs:#(#("x", interiorPos.x), #("y", interiorPos.y), #("z", interiorPos.z)) interiorRot = xmlDoc.createElement "InteriorRotation" appendTo:interiorName attrs:#(#("x", 0), #("y", 0), #("z", interiorHeading)) ) --write out the xml file try ( --get filename to out outFile = getSaveFileName caption:"VFX Test Export" filename:fxPositionsXML types:"Data(*.xml)|*.xml" if outFile != undefined then ( xmlDoc.save outFile ) ) catch ( messageBox "Could not save file, do you have it checked out?" title:"Fail!" return false ) --user message messageBox "Export Finished!" title:"win!" ), on create do ( --get_Interiors() get_InteriorsMaxPositions() get_Locations() ) ) fxTestExporter = FXTestExporterStruct() if FXTestExporterUI != undefined then destroyDialog FXTestExporterUI rollout FXTestExporterUI "FX Test Exporter" ( dotNetControl rsBannerPanel "Panel" pos:[0,0] height:32 width:FXTestExporterUI.width local banner = makeRsBanner dn_Panel:rsBannerPanel wiki:"FX Test Exporter" filename:(getThisScriptFilename()) group "Interior" ( dropdownlist ddlInteriors width:175 dropdownlist ddlLocations width:175 button btnExportBink "Export Bink" width:175 button btnExportLocation "Export Locations" width:175 ) --////////////////////////// --Events dear boy --////////////////////////// on btnExportBink pressed do ( --print "Exporting" success = fxTestExporter.exportSelection() if success then fxTestExporter.writeBinkXML() --attempt tcs fixup for used textures --fxTestExporter.fixupTCS() ) on btnExportLocation pressed do ( success = fxTestExporter.exportSelection() if success then fxTestExporter.writeLocationsXML() ) fn selectLocations arg = ( --print ddlInteriors.selection[arg] theInterior = (for l in fxTestExporter.locations where l.interior == ddlInteriors.selected collect l.items)[1] --print theInterior --for structInst in theInterior do print structInst.location ddlLocations.items = for structInst in theInterior collect structInst.location ) on ddlInteriors selected arg do selectLocations arg on FXTestExporterUI open do ( banner.setup() ddlInteriors.items = sort (for ir in fxTestExporter.locations collect ir.interior) ) ) createDialog FXTestExporterUI width:200 style:#(#style_titlebar, #style_border, #style_sysmenu, #style_minimizebox) fxTestExporter.rolloutUI = FXTestExporterUI