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

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