435 lines
13 KiB
Plaintext
Executable File
435 lines
13 KiB
Plaintext
Executable File
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
|
|
|
|
|
|
|
|
|
|
|