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

1335 lines
51 KiB
Plaintext
Executable File

-- -- ****************************************************************************************
-- -- CS Export Preperation Tools
-- -- ****************************************************************************************
-- -- Basic functionality combined from other scripts.
-- -- Script removes rage shaders and generates standard materials with diffuse maps only.
-- -- In addition to the above:
-- -- Prepare Character selects all meshes and skeleton hierarchy
-- -- Prepare Prop creates dummy meshes and opens export
-- -- Map and vehicle functions are texture switchover only
-- -- ****************************************************************************************
-- -- Stewart Wright - Rockstar North - 19/06/12
-- -- Initial Tool Creation
-- -- ****************************************************************************************
-- -- Andy Davis - Rockstar London - 23/04/13
-- -- DotNet form layout
-- -- Extra material functionality added
-- -- ****************************************************************************************
filein (RsConfigGetWildWestDir() + "script/3dsMax/_config_files/Wildwest_header.ms") --wildwest header
filein (RsConfigGetWildWestDir() + "script/3dsMax/_common_functions/RSL_dotNetUIOps.ms") --RS_dotNetPreset structure
filein (theWildWest + "script/3dsMax/_common_functions/FN_RSTA_Rigging.ms")
-- filein (RsConfigGetWildWestDir() + "script/3dsMax/Characters/Rigging/mrSkeleton_v2/mrSkeleton_2_propRigging_functions.ms") --used for prop root building
filein (RsConfigGetWildWestDir() + "script/3dsMax/Characters/Rigging/mrSkeleton_v2/mrSkeleton_2_functions.ms") --used for prop root building
filein (RsConfigGetWildWestDir() + "script/3dsMax/_common_functions/FN_RSTA_UI.ms")
--have to do a test on project here due to the differing tools.
--this is a temporary fix until I get time to go through the modifications made to the rdr version
--and try to integrate them so they match what should be sitting in wildwest.
if theProject == "rdr3" then
(
RsCollectToolUsageData (getThisScriptFilename())
global CutsceneDataPrepUI
struct CutSceneDataPrepStruct
(
------------------------------------------------------------------------------------------------------------------------------------------
--GENERAL FUNCTIONS
------------------------------------------------------------------------------------------------------------------------------------------
-- fn addDummyData =
-- (
-- format ("Adding max data to dummy node")
--
-- obj = getNodeByName "Dummy01"
--
-- fileNameStr = ("filename = "+ (maxFilePath + maxFileName)+"\r\n")
-- timeStampStr = ("timestamp = " +((localTime) as string)+"\r\n")
-- userStr = ("user = " +(RsUserGetUserName())+"\r\n")
--
-- addFileName = false
-- addtimeStamp = false
-- addUserStr = false
--
-- existingUdp = getUserProp obj "filename"
-- if existingUdp != undefined then
-- (
-- format ("Found udp for filename: "+existingUdp+"\n")
-- setUserProp obj "filename" (maxFilePath + maxFileName)
-- )
-- else
-- (
-- addFileName = true
-- )
--
-- existingUdp = getUserProp obj "timestamp"
-- if existingUdp != undefined then
-- (
-- format ("Found udp for timestamp: "+existingUdp+"\n")
-- setUserProp obj "timestamp" ((localTime) as string)
-- )
-- else
-- (
-- addtimeStamp = true
-- )
--
-- existingUdp = getUserProp obj "user"
-- if existingUdp != undefined then
-- (
-- format ("Found udp for user: "+existingUdp+"\n")
-- setUserProp obj "user" (RsUserGetUserName())
-- )
-- else
-- (
-- addUserStr = true
-- )
--
-- currentudp = getUserPropBuffer obj
--
-- if addFileName == true do
-- (
-- newUdp = (currentUdp+"\r\n"+fileNameStr)
-- setUserPropBuffer obj newUdp
-- )
--
-- currentudp = getUserPropBuffer obj
--
-- if addtimeStamp == true do
-- (
-- newUdp = (currentUdp+"\r\n"+timeStampStr)
-- setUserPropBuffer obj newUdp
-- )
-- currentudp = getUserPropBuffer obj
--
-- if addUserStr == true do
-- (
-- newUdp = (currentUdp+"\r\n"+userStr)
-- setUserPropBuffer obj newUdp
-- )
-- ),
fn CaptureDisplay =
(
filein (RsConfigGetWildWestDir() + "script/3dsMax/Cutscene/CutsceneCaptureSphereDisplay.ms")
),
fn NukeMaterials =
(
print "Wiping Materials"
if queryBox "I will attempt to delete all materials in the scene.\r\nDo you want to continue?" beep:false title:"Materials Export Manager" do
(
clear_all_materials() --appears to be an external generic script
kill_materials() --appears to be an external generic script
)
),
fn PrepareCharacter =
(
print "Preparing character"
local pedMeshes = this.ShowSkinningAndBones()
this.SortAndSwitch pedMeshes
this.WriteSelectionSets()
-- this.addDummyData()
RSTA_addDummyData()
),
fn PrepareExpressions =
(
print "Preparing expressions"
filein (RsConfigGetWildWestDir() + "script/3dsMax/Characters/Rigging/usefulScripts/RSTA_cleanExpressionControllersForMotionBuilder.ms")
--from "X:\gta5\tools\wildwest\script\3dsMax\Characters\Rigging\riggingToolsGUI.ms" lines 154 -> 155
filein (RsConfigGetWildWestDir() + "script/3dsMax/Characters/Rigging/findExpressionObjects.ms")
print "Expression set Created"
exprItems = #()
selCount = getNumNamedSelSets()
for i = selCount to 1 by -1 do
(
if getNamedSelSetName i == "*expressionsToExport" then
(
setItems = getNamedSelSetItemCount i
for a = 1 to setItems do
(
thisItem = getNamedSelSetItem i a
appendIfUnique exprItems thisItem
)
)
)
select exprItems
--from "X:\gta5\tools\wildwest\script\3dsMax\Characters\Rigging\ExpressionExporter\expressionGUI.ms" lines 161 -> 164
filein (RsConfigGetWildWestDir() + "script/3dsMax/Characters/Rigging/ExpressionExporter/objectOutput.ms")
filein (RsConfigGetWildWestDir() + "script/3dsMax/Characters/Rigging/ExpressionExporter/expressionOutputXML.ms")
print "Expressions saved"
),
fn Export mode =
(
case mode of
(
#cutscene:
(
messagebox "Export #cutscene"
)
#game:
(
messagebox "Export #game"
)
)
),
fn PrepareProp =
(
if selection.count == 1 then
(
thisProp = getCurrentSelection()
--===========================================================================================================================
--a section to handle gun magazine meshes - bug 808586
gunMag == false
propName = upperCase thisProp[1].name --get the prop name
filterPropName = filterString propName "_" --filter the name for breaks
shortPropName = #() --an array to hold the shortened filter data
for x=1 to filterPropName.count do (append shortPropName (subString filterPropName[x] 1 3))
magCheck = findItem shortPropName "MAG"
if magCheck !=0 do (if filterPropName[magCheck].count == 4 do gunMag = true)
--===========================================================================================================================
if ((isMeshSkinned thisProp[1]) == true) and (gunMag != true) then--if the mesh is skinned
(
print "Preparing skinned prop"
thisProp = getCurrentSelection()
this.SortAndSwitch thisProp
this.SkinnedProp thisProp[1]
)
else
(
if queryBox "This appears to be an unskinned prop.\r\nI will attempt create a rig root setup for it.\r\nDo you want to continue?" beep:false title:"Materials Export Manager" do
(
print "Preparing unskinned prop"
thisProp = getCurrentSelection()
this.SortAndSwitch thisProp
this.UnskinnedProp thisProp[1]
)
)
)
else (messageBox "Please run with only one object selected.")
),
fn PrepareVehicle =
(
print "Preparing vehicle"
if selection.count != 0 then
(
vehicleMeshes = getCurrentSelection()
this.SortAndSwitch vehicleMeshes
this.VehicleSetup()
)
else
(
if queryBox "Nothing selected.\r\nI will attempt to perform this on all objects in the scene.\r\nThis could take a while.\r\nDo you want to continue?" beep:false do
(
hideByCategory.none() -- unhide all by categry
max unhide all -- unhide all
max select all --select all
vehicleMeshes = getCurrentSelection()
clearSelection()
this.SortAndSwitch vehicleMeshes
this.VehicleSetup()
)
)
),
fn PrepareMap =
(
print "Preparing map"
-- if selection.count != 0 then
-- (
-- mapMeshes = getCurrentSelection()
-- this.SortAndSwitch mapMeshes
-- )
-- else
-- (
-- if queryBox "Nothing selected.\r\nI will attempt to perform this on all objects in the scene.\r\nThis could take a while.\r\nDo you want to continue?" beep:false do
-- (
-- hideByCategory.none() -- unhide all by categry
-- max unhide all -- unhide all
-- max select all --select all
-- mapMeshes = getCurrentSelection()
-- clearSelection()
-- this.SortAndSwitch mapMeshes
-- )
if queryBox "I will attempt to delete all materials in the scene.\r\nDo you want to continue?" beep:false do
(
clear_all_materials()
kill_materials()
this.CSMapExport()
)
-- )
),
fn SetupEnvironment =
(
filein (RsConfigGetWildWestDir() + "script/3dsMax/Cutscene/cs_enviroment_setup.ms")
),
------------------------------------------------------------------------------------------------------------------------------------------
--WORKHORSE FUNCTIONS
------------------------------------------------------------------------------------------------------------------------------------------
fn CullTextures =
(
print "Cull Textures"
local shaders = getClassInstances StandardMaterial
local diffuseMaps = for item in shaders where item.diffuseMap != undefined collect item.diffuseMap
local buffer = #()
local mapKeepList = #() --array of map id's that we are going to keep
--work out which maps to keep
(
if (CutsceneDataPrepUI.AlphaCheckBox.Checked) then
append mapKeepList 6
)
clearlistener()
-- for item in diffuseMaps where item.bitmap != undefined do
for item in diffuseMaps do
(
try
(
item.bitmap
append buffer item
)
catch (print "problem with " + item as string)
)
diffuseMaps = makeUniqueArray buffer
for item in diffuseMaps do
(
print item.bitmap
)
-- print diffuseMaps
),
fn UnskinnedProp theProp =
--theProp = a single mesh
(
convertto theProp editable_poly --convert mesh to edit poly
ResetTransform theProp --reset xforms
convertto theProp editable_poly --convert mesh to edit poly again to be sure
--move selected to 0,0,0 worldspace
in coordsys world theProp.pos = [0,0,0]
print "Prop defined and moved to center"
-- newRootSystem = BuildRigRootSystem theProp
RSTA_buildPropRoot theProp false false
-- rootObj = newRootSystem[2][1]--this should be the dummy
-- movObj = newRootSystem[2][2]--this should be the mover
rootObj = getNodeByName ("Dummy_"+theProp.name)
movObj = getNodeByName ("Mover_"+theProp.name)
local newRootSystem = #(
#(),
#()
)
newRootSystem[1] = RSTA_getAllChildren rootObj arr:newRootSystem[1]#()
if classOf rootObj == Dummy do--we are going to tag the dummy with the filename
(
this.DelFileInfoTags rootObj --delete the tags off the children of the export dummy
this.TagFileNameInfo rootObj --tag mesh information
)
for boneDel=1 to newRootSystem[1].count do
(
if newRootSystem[1][boneDel] != rootObj then
(
if newRootSystem[1][boneDel] != movObj then
(
delete newRootSystem[1][boneDel]
)
)
)
theProp.parent = movObj--parent the prop to the mover
exportMeshes = #()
this.CollectChildren rootObj &exportMeshes includeParent:true includeHidden:true --collect all the skeleton heirarchy
appendIfUnique exportMeshes theProp
hideByCategory.none() -- unhide all by categry
max unhide all -- unhide all
clearSelection()
select exportMeshes
max hide inv
--
-- Thanh: Automate the export process, including texture filepath update, and p4 checkin.
--
getPath = getSavePath initialDir: (RsConfigGetProjRootDir() + "art\\animation\\resources\\props")
presetLocation = "X:\\tphan\\script\\max\\RS FBX Export Preset.fbxexportpreset\\"
lNewFilePath = undefined
lNewTxtPath = undefined
lObjName = undefined
if getPath != undefined then (
for item in selection do (
if (filterstring item.name "_")[1] == "Mover" do (
lOldTxtPath = undefined
lMat = undefined
lObj = item.children[1]
if (ClassOf item.children[1].material) as string == "Standardmaterial" then (
lMat = item.children[1].material
lOldTxtPath = lMat.diffusemap.filename
)
else (
lMat = item.children[1].material[1]
lOldTxtPath = lMat.diffusemap.filename
)
lTxtNameArray = filterstring lOldTxtPath "\\"
lTxtName = lTxtNameArray[lTxtNameArray.count]
lObjName = lObj.name
lFileName = lObjName + ".FBX"
lNewTxtFilePath = getPath + "\\" + lObjName + ".fbm"
lNewTxtPath = getPath + "\\" + lObjName + ".fbm\\" + lTxtName
lNewFilePath = getPath + "\\" + lFileName
makeDir lNewTxtFilePath
if doesFileExist lNewTxtPath do (
print "Deleting file"
setFileAttribute lNewTxtPath #readOnly false
deleteFile lNewTxtPath
)
if gRsPerforce.connected() == false then gRsPerforce.connect()
gRsPerforce.sync lOldTxtPath silent:true
copyfile lOldTxtPath lNewTxtPath
lMat.diffusemap.filename = lNewTxtPath
)
)
if lNewFilePath != undefined then (
-- EXPORT SETTINGS ----------------------------
--Geometry------------------------------------------------------------------------
FBXExporterSetParam "SmoothingGroups" false
FBXExporterSetParam "NormalsPerPoly" false
FBXExporterSetParam "TangentSpaceExport" false
FBXExporterSetParam "SmoothMeshExport" false
FBXExporterSetParam "Preserveinstances" false
FBXExporterSetParam "SelectionSetExport" false
FBXExporterSetParam "GeomAsBone" true
FBXExporterSetParam "ColladaTriangulate" false
FBXExporterSetParam "PreserveEdgeOrientation" false
--Animation------------------------------------------------------------------------
FBXExporterSetParam "Animation" false
--Cameras------------------------------------------------------------------------
FBXExporterSetParam "Cameras" false
--Lights------------------------------------------------------------------------
FBXExporterSetParam "Lights" false
--Embed Media--------------------------------------------------------------------
FBXExporterSetParam "EmbedTextures" false
--Units----------------------------------------------------------------------------
FBXExporterSetParam "ScaleFactor" 100
--Axis Conversion-----------------------------------------------------------------
FBXExporterSetParam "AxisConversionMethod" "None"
FBXExporterSetParam "UpAxis" "Y"
--UI----------------------------------------------------------------
FBXExporterSetParam "ShowWarnings" true
FBXExporterSetParam "GenerateLog" true
--FBX File Format----------------------------------------------------------------
FBXExporterSetParam "ASCII" false
FBXExporterSetParam "FileVersion" "FBX201000"
exportFile lNewFilePath #noPrompt selectedOnly:true using:FBXEXP
if gRsPerforce.connected() == false then gRsPerforce.connect()
lChangelist = gRsPerforce.createChangelist ("Prop and Texture FBX Conversion: " + lObjName)
gRsPerforce.add lNewTxtPath
gRsPerforce.addToChangelist lChangelist lNewTxtPath
gRsPerforce.add lNewFilePath
gRsPerforce.addToChangelist lChangelist lNewFilePath
gRsPerforce.edit lNewFilePath
gRsPerforce.addToChangelist lChangelist lNewFilePath
)
else (
print "Unsuccessful export. Unable to acquire filepath."
)
)
else (
print "USER CANCELLED."
)
--hacky export selected as method. needs better way.
--actionMan.executeAction 0 "40373" -- File: Export Selected
),--end UnskinnedProp
--****************************************************************************************
fn SkinnedProp theProp =
--theProp = a single mesh
(
exportMeshes = #(theProp)
skinningBones = #()
objectsToShow = #()
rootObj = undefined
if (isMeshSkinned theProp) == true do--if the mesh is skinned
(
skinMod = theProp.modifiers[#Skin]
modPanel.setCurrentObject skinMod
skinnedBoneCount = skinops.getNumberBones skinMod
if skinnedBoneCount > 0 do --if there are bones in the skin modifier
(
realBone = getBoneFromSkin skinMod 1 --find a real bone in the scene
rootObj = WWfindRootObject realBone --find the root of the heirarchy
this.CollectChildren rootObj &skinningBones includeParent:true includeHidden:true --collect all the skeleton heirarchy
)
)--if the mesh is skinned remember it
if classOf rootObj == Dummy do--we are going to tag the dummy with the filename
(
this.DelFileInfoTags rootObj --delete the tags off the children of the export dummy
this.TagFileNameInfo rootObj --tag mesh information
)
objectsToShow = exportMeshes
join objectsToShow skinningBones
selectionsets["*CS Export"] = objectsToShow --create selection set of everything
hideByCategory.none() -- unhide all by categry
max unhide all -- unhide all
clearSelection()
select objectsToShow
max hide inv
--hacky export selected as method. needs better way.
actionMan.executeAction 0 "40373" -- File: Export Selected
),--end SkinnedProp
--attempt to find the export dummy
fn findTheDummy =
(
characterNode = undefined
try
(
selectByWildCard "head_000" --there should always be a head mesh
if selection.count > 0 then --if we find at least 1 mesh
(
obj = selection[1]
exportDummy = WWfindRootObject obj
clearSelection()
exportDummy --pass out the export dummy
)
else
(
print "I couldn't find my head"
)
)catch()
),--end findTheDummy
-- collects all children recursively. arguments:
-- found on http://forums.cgsociety.org/showpost.php?p=4427477&postcount=2
fn CollectChildren obj &allChildren includeParent:false includeHidden:false =
(
-- check if object should be collected
if (includeHidden or not obj.isHiddenInVpt) and includeParent and finditem allChildren obj == 0 then
append allChildren obj
-- collect current object's children
for c in obj.children do this.CollectChildren c &allChildren includeParent:true includeHidden:includeHidden
), -- end collectChildren
-- delete any mesh info tags. this includes selection sets and meshnames
-- deleteFromThese = the meshes to delete from
fn DelFileInfoTags deleteThisMesh =
(
keepUDP = #()
currentUDP = getUserPropbuffer deleteThisMesh
filterUDP = filterString currentUDP "\r\n"
for f = 1 to filterUDP.count do
(
tempUDP = uppercase filterUDP[f]
shortUDP = substring tempUDP 1 7
if (shortUDP != "MAXFILE") then
append keepUDP tempUDP
)
tag = ""
if keepUDP.count == 0 then
setUserPropbuffer deleteThisMesh tag
else
for k = 1 to keepUDP.count do
(
tag = tag + keepUDP[k] + "\r\n"
setUserPropbuffer deleteThisMesh tag
)
this.ReorderTags deleteThisMesh
),-- end delFileInfoTags
-- go through all geometry and tag it with the maxscene name
fn TagFileNameInfo meshToTag =
(
tagThis = ""
tagThis = "MaxFile=" + maxfilepath + maxfilename
oldTag = getUserPropbuffer meshToTag
tagThis = oldTag+"\r\n"+tagThis
tagThis = uppercase tagThis
setUserPropbuffer meshToTag tagThis
this.ReorderTags meshToTag --tidy up the tags
),-- end tagFileNameInfo
-- tidy up the user defined properties by sorting it alphabetically
fn ReorderTags tagMe =
(
currentUDP = getUserPropbuffer tagMe
filterUDP = filterString currentUDP "\r\n"
alphUDP = sort filterUDP
tag = ""
for t = 1 to alphUDP.count do
(
tag = tag + alphUDP[t] + "\r\n"
setUserPropbuffer tagMe tag
)
),-- end reorderTags
fn ShowSkinningAndBones =
(
if ((progBar != undefined) and (progBar.isDisplayed)) do (destroyDialog progBar)
CreateDialog progBar width:300 Height:30
progBar.prog.color = [225, 110, 35] --green
max modify mode
exportMeshes = #()
skinningBones = #()
objectsToShow = #()
characterNode = this.FindTheDummy() --find the export dummy
if classOf characterNode == Dummy do--we are going to tag the dummy with the filename
(
this.DelFileInfoTags characterNode --delete the tags off the children of the export dummy
this.TagFileNameInfo characterNode --tag mesh information
)
if characterNode != undefined then
(
progBar.prog.value = 20
this.CollectChildren characterNode &exportMeshes includeParent:false includeHidden:true --collect all the skeleton heirarchy
if exportMeshes.count > 0 do
(
progBar.prog.value = 40
for checkMesh = 1 to exportMeshes.count while skinningBones.count == 0 do
(
if (isMeshSkinned exportMeshes[checkMesh]) == true do--if the mesh is skinned
(
progBar.prog.value = 60
skinMod = exportMeshes[checkMesh].modifiers[#Skin]
modPanel.setCurrentObject skinMod
skinnedBoneCount = skinops.getNumberBones skinMod
if skinnedBoneCount > 0 do --if there are bones in the skin modifier
(
progBar.prog.value = 80
realBone = getBoneFromSkin skinMod 1 --find a real bone in the scene
rootObj = WWfindRootObject realBone --find the root of the heirarchy
this.CollectChildren rootObj &skinningBones includeParent:true includeHidden:true --collect all the skeleton heirarchy
progBar.prog.value = 100
)
)--if the mesh is skinned remember it
)
)
objectsToShow = exportMeshes
join objectsToShow skinningBones
appendIfUnique objectsToShow characterNode
selectionsets["*CS Export"] = objectsToShow --create selection set of everything
hideByCategory.none() -- unhide all by categry
max unhide all -- unhide all
clearSelection()
select objectsToShow
max hide inv
(destroyDialog progBar)
)
else
(
progBar.prog.color = [255,0,0]--red
progBar.prog.value = 100
print "Couldn't find the export dummy!"
(destroyDialog progBar)
)
exportMeshes--pass out the meshes for the shader change
),--end showSkinningAndBones
fn VehicleSetup =
--copied from vehicle_export_setup.ms
(
savePath = theProjectRoot + "/art/animation/resources/vehicles/"
maxName = undefined
vehicleMesh = #()
parentDummy = undefined
vehicleSkel = #()
everything = #()
--this is a neater way of getting all children. alt method to using actionMan.executeAction 0 "40180"
fn selectHierarchy whatGeo =
(
for p in whatGeo do
(
if p.children != undefined do
(
selectmore p.children
)
)
)--end selectHierarchy
maxName = filterstring maxFileName "_" --this should get the prefix of vehicle name which is always vehiclename_skinned.max
chassisBoneName = (maxName[1]+"_Skel")
try (delete $Dummy01) catch()--try and delete a dummy mesh if it exists already
parentDummy = dummy pos:[0,0,0]
parentDummy.name = "Dummy01"
skel = getNodeByName chassisBoneName
if (skel != undefined) then
(
skel.parent = parentDummy
print (chassisBoneName+" parented to "+parentDummy.name)
hideByCategory.none()--unhide everything by category
unhide (for obj in objects where obj.ishidden collect obj) --unhide all
maxName = filterstring maxFileName "_"
meshName = maxName[1] + "_skin"
try
(
vehicleMesh = getNodeByName meshName
) catch (print ("Couldn't find " +meshName))
hideByCategory.none()--unhide everything by category
unhide (for obj in objects where obj.ishidden collect obj) --unhide all
try
(
selectHierarchy parentDummy --select the children (and children's children) of the parentdummy
selectmore parentDummy --add the dummy to the selection
selectionsets["*vehicleSkel"] = selection --create selection set of everything
vehicleSkel = getCurrentSelection()
clearSelection()
print "vehicle skeleton found"
) catch (messagebox "Can't Find Parent Dummy" title:"Materials Export Manager") --attempt to select the export dummy
everything = vehicleSkel
appendIfUnique everything vehicleMesh
select everything
saveFile = savePath + maxName[1]
exportFile saveFile #noPrompt selectedOnly:true using:FBXEXP
messageText = maxName[1] + " exported as FBX to " + saveFile + ".fbx"
messageBox messageText title:"Materials Export Manager"
)
else
(
messageBox "Selected vehicle has no skeleton." title:"Materials Export Manager"
)
),--end vehicleSetup
--function to filter selection and switch materials
fn SortAndSwitch meshesToSort =
--meshesToSort = an array of objects
(
if ((progBar != undefined) and (progBar.isDisplayed)) do (destroyDialog progBar)
CreateDialog progBar width:300 Height:30
progBar.prog.color = [10,210,10] --green
meshesToChange = #()
if meshesToSort.count > 0 do
(
for allSel=1 to meshesToSort.count do
(
if superClassOf meshesToSort[allSel] == GeometryClass do append meshesToChange meshesToSort[allSel]
)
if meshesToChange.count > 0 do
(
print "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv"
print "Starting Texture Swtich"
startTimer = timestamp()
print ("Converting "+ (meshesToChange.count as string) + " mesh materials.")
for selMesh=1 to meshesToChange.count do
(
if meshesToChange[selMesh].material != undefined do
(
mlib[24] = meshesToChange[selMesh].material
this.SwitchRageToStd 24
meshesToChange[selMesh].material = mlib[24]
)
progBar.prog.value = ((100* selMesh)/meshesToChange.count)
)
endTimer = timeStamp()
print "Texture Switch Complete"
format "Time taken: %s\n" ((endTimer - startTimer) / 1000.0)
print "^^^^^^^^^^^^^^^^^^^^^^"
)
)
(destroyDialog progBar)
),--end sortAndSwitch
--function for getting the shader/material values and storing them
fn SwitchRageToStd matID =
(
if classof mlib[MatID] == Multimaterial then --if the material is a multisub then we want to look in it
(
for SubID = 1 to mlib[MatID].numSubs do --for every multisub in this material
(
if classof mlib[matid][subid] == Rage_Shader then
(
varValue = ""--set an undefined value for the bitmap path
for x=1 to RstGetVariableCount mlib[matid][subid] do
(
--if the variable type is texmap, the map type is diffuse and the path is not undefined
if (uppercase (RstGetVariableType mlib[matid][subid] x)) == "TEXMAP" and (findstring (uppercase (RstGetVariableName mlib[matid][subid] x)) "DIFFUSE TEXTURE") != undefined and (RstGetVariable mlib[matid][subid] x) != "" do
(
varValue = RstGetVariable mlib[matid][subid] x--store the bitmap path
)
)
mlib[matid][subid] = Standardmaterial () --change it to a standard material
mlib[matid][subid].diffusemap = Bitmaptexture fileName:varValue --set the diffuse map to the value we found in the rage shader
mlib[matid][subid].showInViewport = true
)
else
(
if classof mlib[matid][subid] == Standardmaterial then
(
if mlib[matid][subid].diffusemap != undefined do
(
varValue = mlib[matid][subid].diffusemap.filename
if varValue != undefined do
(
mlib[matid][subid] = Standardmaterial () --change it to a standard material
mlib[matid][subid].diffusemap = Bitmaptexture fileName:varValue --set the diffuse map to the value we found in the rage shader
mlib[matid][subid].showInViewport = true
)
)
)
else()
)
)
)
else
(
if classof mlib[matid] == Rage_Shader then
(
varValue = ""--set an undefined value for the bitmap path
for x=1 to RstGetVariableCount mlib[matid] do
(
--if the variable type is texmap, the map type is diffuse and the path is not undefined
if (uppercase (RstGetVariableType mlib[matid] x)) == "TEXMAP" and (findstring (uppercase (RstGetVariableName mlib[matid] x)) "DIFFUSE TEXTURE") != undefined and (RstGetVariable mlib[matid] x != "") do
(
varValue = RstGetVariable mlib[matid] x--store the bitmap path
)
)
mlib[matid] = Standardmaterial () --change it to a standard material
mlib[matid].diffusemap = Bitmaptexture fileName:varValue --set the diffuse map to the value we found in the rage shader
mlib[matid].showInViewport = true
)
else
(
if classof mlib[matid] == Standardmaterial then
(
if mlib[matid].diffusemap != undefined do
(
varValue = mlib[matid].diffusemap.filename
if varValue != undefined do
(
mlib[matid] = Standardmaterial () --change it to a standard material
mlib[matid].diffusemap = Bitmaptexture fileName:varValue --set the diffuse map to the value we found in the rage shader
mlib[matid].showInViewport = true
)
)
)
else()
)
)
),--end switchRageToStd
--function for writing out the selection sets to a text file
fn WriteSelectionSets =
(
everything = #()
outputFolder = maxfilepath --output folder is the same as the max file
outputFile = outputFolder + "SelectionSets.txt" --save the file as "SelectionSets.txt"
selectionSetFile = createFile outputFile --now we make the text file using the above settings
--fileHeadText = ("Created on " + localtime)
--print fileHeadText to: selectionSetFile --write the system time to the text file
for ss = 1 to selectionsets.count do
(
singleSelSet = #(infoText = ("Selection Set " + ss as string + " of " + selectionsets.count as string)) --some header information
selSetName = SelectionSets[ss].name --the name of the selection set
append singleSelSet selSetName
matchSS = for obj in SelectionSets[ss] collect obj.name --turn sel.set into array
append singleSelSet matchSS
append everything singleSelSet
)
print everything to: selectionSetFile
close selectionSetFile --housekeeping. this closes the txt file
),--end writeSelectionSets
--function to setup map for cs export
--copied code from cs_enviroment_setup.ms
fn CSMapExport =
(
--Unhide & unfreeze the dummy01 node
max unhide all
max unfreeze all
--Select the original scene root, it can be called either Dummy01 or Dummy001
try(
select $Point01
$.name = "PointOrig"
)catch()
try(
select $Point001
$.name = "PointOrig"
)catch()
--Copy the "Point Orig" and rename
Copy $
select $PointOrig001
$.name = "SetRoot"
--Set selection filter to select the geo and parent selection to the setroot
setSelectFilter 2
max select all
$.parent = $SetRoot
--Return Selection filter to all
SetSelectFilter 1
--Clear the selection
clearSelection()
--Create "PointZerod2"
Point pos:[0,0,0] isSelected:on
$.name = "PointZerod2"
--Align Setroot to "PointZerod2"
select $SetRoot
$.pos = $PointZerod2.pos
--Parent the "PointZerod2" & "Point Orig" to the SetRoot
select $PointZerod2
$.parent = $SetRoot
select $PointOrig
$.parent = $SetRoot
--Clear the selection
clearSelection()
--select the "PointOrig" & Get offset information
select $PointOrig
offsetposition = $PointOrig.pos
Positionfilter = (offsetposition as string)
Position_offset_values = filterstring Positionfilter "[ ]"
PointOrigangle = $PointOrig.rotation as eulerAngles
offsetrotation= PointOrigangle.Z
Rotation_offset_values = (offsetrotation as string )
--Time & user stamp
timedate = localtime
Updatedby = sysInfo.username
Filename = maxFileName as string
Setname = filterString Filename "."
-- create an offset co-ordinate file
makeDir (RsConfigGetArtDir() + "animation/resources/sets/Offsets")
output_name = (RsConfigGetArtDir() + "animation/resources/sets/Offsets/" + Setname[1] + ".log")
outputFile = createfile output_name
format (("<<<<<< " +Setname[1] +" >>>>>>" )+"\n") to:outputFile
format (("Last updated by " + Updatedby + " on the " + timedate)+"\n") to:outputFile
format (("" )+"\n") to:outputFile
format (("Position Offset = " + Position_offset_values[1] )+"\n") to:outputFile
format (("Rotation Offset = " + Rotation_offset_values )+"\n") to:outputFile
close outputFile
)--csMapExport
)
struct CutsceneDataPrepUIStruct
(
Form,
Table,
ToolTip,
PrepareCharacterButton,
PrepareExpressionsButton,
ExportGameButton,
ExportCutSceneButton,
ShowCapturesButton,
NukeMaterialsButton,
SetupEnvironmentButton,
CheckBoxTable,
AlphaCheckBox,
SpecularCheckBox,
NormalCheckBox,
AllMapsCheckBox,
ModeComboBox,
CharacterTable,
PropTable,
VehicleTable,
MapTable,
IniFilePath = (RsConfigGetWildWestDir() + "script/3dsMax/_config_files/Cutscene_Tools.ini"),
Method = CutSceneDataPrepStruct(),
------------------------------------------------------------------------------------------------------------------------------------------
--EVENT HANDLERS
------------------------------------------------------------------------------------------------------------------------------------------
fn CaptureDisplay = CutsceneDataPrepUI.Method.CaptureDisplay(),
fn NukeMaterials = CutsceneDataPrepUI.Method.NukeMaterials(),
fn PrepareCharacter = CutsceneDataPrepUI.Method.PrepareCharacter(),
fn PrepareExpressions = CutsceneDataPrepUI.Method.PrepareExpressions(),
fn ExportForCutscene = CutsceneDataPrepUI.Method.Export #cutscene,
fn ExportForGame = CutsceneDataPrepUI.Method.Export #game,
fn PrepareProp = CutsceneDataPrepUI.Method.PrepareProp(),
fn PrepareVehicle = CutsceneDataPrepUI.Method.PrepareVehicle(),
fn PrepareMap = CutsceneDataPrepUI.Method.PrepareMap(),
fn SetupEnvironment = CutsceneDataPrepUI.Method.SetupEnvironment(),
-- fn ToggleAllMaps =
-- (
-- if (CutsceneDataPrepUI.AllMapsCheckBox.Checked) then
-- (
-- CutsceneDataPrepUI.AlphaCheckBox.Enabled = false
-- CutsceneDataPrepUI.SpecularCheckBox.Enabled = false
-- CutsceneDataPrepUI.NormalCheckBox.Enabled = false
-- )
--
-- else
-- (
-- CutsceneDataPrepUI.AlphaCheckBox.Enabled = true
-- CutsceneDataPrepUI.SpecularCheckBox.Enabled = true
-- CutsceneDataPrepUI.NormalCheckBox.Enabled = true
-- )
-- ),
fn UpdateTool s e =
(
CutsceneDataPrepUI.InstallTable CutsceneDataPrepUI.ModeComboBox.SelectedIndex
),
------------------------------------------------------------------------------------------------------------------------------------------
--OPEN/CLOSE FUNCTIONS
------------------------------------------------------------------------------------------------------------------------------------------
fn FormClose =
(
setINISetting CutsceneDataPrepUI.IniFilePath "CutsceneDataPrepUI" "WinLocX" (CutsceneDataPrepUI.Form.Location.x as string)
setINISetting CutsceneDataPrepUI.IniFilePath "CutsceneDataPrepUI" "WinLocY" (CutsceneDataPrepUI.Form.Location.y as string)
setINISetting CutsceneDataPrepUI.IniFilePath "CutsceneDataPrepUI" "WinWidth" (CutsceneDataPrepUI.Form.Width as string)
setINISetting CutsceneDataPrepUI.IniFilePath "CutsceneDataPrepUI" "WinHeight" (CutsceneDataPrepUI.Form.Height as string)
setINISetting CutsceneDataPrepUI.IniFilePath "CutsceneDataPrepUI" "Mode" (CutsceneDataPrepUI.ModeComboBox.SelectedIndex as string)
-- setINISetting CutsceneDataPrepUI.IniFilePath "CutsceneDataPrepUI" "AlphaChecked" (CutsceneDataPrepUI.AlphaCheckBox.Checked as string)
-- setINISetting CutsceneDataPrepUI.IniFilePath "CutsceneDataPrepUI" "SpecularChecked" (CutsceneDataPrepUI.SpecularCheckBox.Checked as string)
-- setINISetting CutsceneDataPrepUI.IniFilePath "CutsceneDataPrepUI" "NormalChecked" (CutsceneDataPrepUI.NormalCheckBox.Checked as string)
(dotnetclass "System.gc").ReRegisterForFinalize CutsceneDataPrepUI.ModeComboBox
CutsceneDataPrepUI.ModeComboBox.Dispose()
),
fn FormOpen =
(
--default values
local WinLocX = 100
local WinLocY = 100
local WinWidth = 200
local WinHeight = 200
local mode = 0
-- local alphaChecked = true
-- local specularChecked = true
-- local normalChecked = true
try
(
WinLocX = getINISetting CutsceneDataPrepUI.IniFilePath "CutsceneDataPrepUI" "WinLocX" as integer
WinLocY = getINISetting CutsceneDataPrepUI.IniFilePath "CutsceneDataPrepUI" "WinLocY" as integer
WinWidth = getINISetting CutsceneDataPrepUI.IniFilePath "CutsceneDataPrepUI" "WinWidth" as integer
WinHeight = getINISetting CutsceneDataPrepUI.IniFilePath "CutsceneDataPrepUI" "WinHeight" as integer
mode = getINISetting CutsceneDataPrepUI.IniFilePath "CutsceneDataPrepUI" "Mode" as integer
-- alphaChecked = getINISetting CutsceneDataPrepUI.IniFilePath "CutsceneDataPrepUI" "AlphaChecked" as BooleanClass
-- specularChecked = getINISetting CutsceneDataPrepUI.IniFilePath "CutsceneDataPrepUI" "SpecularChecked" as BooleanClass
-- normalChecked = getINISetting CutsceneDataPrepUI.IniFilePath "CutsceneDataPrepUI" "NormalChecked" as BooleanClass
)
catch()
CutsceneDataPrepUI.Form.Location = dotNetObject "system.drawing.point" WinLocX WinLocY
-- CutsceneDataPrepUI.Form.Size = dotNetObject "System.Drawing.Size" WinWidth WinHeight
CutsceneDataPrepUI.Form.Width = WinWidth
-- CutsceneDataPrepUI.ToggleAllMaps()
CutsceneDataPrepUI.ModeComboBox.SelectedIndex = mode
-- CutsceneDataPrepUI.AlphaCheckBox.Checked = alphaChecked
-- CutsceneDataPrepUI.SpecularCheckBox.Checked = specularChecked
-- CutsceneDataPrepUI.NormalCheckBox.Checked = normalChecked
CutsceneDataPrepUI.InstallTable mode
),
------------------------------------------------------------------------------------------------------------------------------------------
--GENERAL FUNCTIONS
------------------------------------------------------------------------------------------------------------------------------------------
--function removes the previous button table and replaces it with the table corresponding with the current mode
fn InstallTable index =
(
local tableHeight = 112
if CutsceneDataPrepUI.Table.Controls.count == 3 then
CutsceneDataPrepUI.Table.Controls.RemoveAt 2
case index of
(
0:
(
CharacterTable = dotNetObject "TableLayoutPanel"
CharacterTable.RowCount = 4
CharacterTable.Margin = dotNetObject "System.Windows.Forms.Padding" 2
CharacterTable.Dock = RS_dotNetPreset.DS_Fill
-- CharacterTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 75) --checkboxes
CharacterTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 25)
CharacterTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 25)
CharacterTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 25)
CharacterTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 25)
CharacterTable.ColumnCount = 1
CharacterTable.ColumnStyles.add (RS_dotNetObject.columnStyleObject "percent" 100)
-- CharacterTable.Controls.Add CutsceneDataPrepUI.CheckBoxTable 0 0
PrepareCharacterButton = RS_DotNetUI.InitButton "Prepare Character"
dotNet.AddEventHandler PrepareCharacterButton "Click" PrepareCharacter
CharacterTable.Controls.Add PrepareCharacterButton 0 0
PrepareExpressionsButton = RS_DotNetUI.InitButton "Prepare Expressions"
dotNet.AddEventHandler PrepareExpressionsButton "Click" PrepareExpressions
CharacterTable.Controls.Add PrepareExpressionsButton 0 1
-- ExportCutSceneButton = RS_DotNetUI.InitButton "Export For Cutscene"
-- dotNet.AddEventHandler ExportCutSceneButton "Click" ExportForCutscene
-- CharacterTable.Controls.Add ExportCutSceneButton 0 3
-- ExportGameButton = RS_DotNetUI.InitButton "Export For Game"
-- dotNet.AddEventHandler ExportGameButton "Click" ExportForGame
-- CharacterTable.Controls.Add ExportGameButton 0 4
NukeMaterialsButton = RS_DotNetUI.InitButton "Nuke Materials"
dotNet.AddEventHandler NukeMaterialsButton "Click" NukeMaterials
CharacterTable.Controls.Add NukeMaterialsButton 0 2
CutsceneDataPrepUI.Table.Controls.Add CharacterTable 0 2
tableHeight += (25 * 3)
)
1:
(
PropTable = dotNetObject "TableLayoutPanel"
PropTable.RowCount = 2
PropTable.Margin = dotNetObject "System.Windows.Forms.Padding" 2
PropTable.Dock = RS_dotNetPreset.DS_Fill
PropTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 25)
PropTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 25)
PropTable.ColumnCount = 1
PropTable.ColumnStyles.add (RS_dotNetObject.columnStyleObject "percent" 100)
PreparePropButton = RS_DotNetUI.InitButton "Prepare Prop"
PropTable.Controls.Add PreparePropButton 0 0
dotNet.AddEventHandler PreparePropButton "Click" PrepareProp
NukeMaterialsButton = RS_DotNetUI.InitButton "Nuke Materials"
dotNet.AddEventHandler NukeMaterialsButton "Click" NukeMaterials
PropTable.Controls.Add CutsceneDataPrepUI.NukeMaterialsButton 0 1
CutsceneDataPrepUI.Table.Controls.Add PropTable 0 2
tableHeight += (25 * 2)
)
2:
(
VehicleTable = dotNetObject "TableLayoutPanel"
VehicleTable.RowCount = 2
VehicleTable.Margin = dotNetObject "System.Windows.Forms.Padding" 2
VehicleTable.Dock = RS_dotNetPreset.DS_Fill
VehicleTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 25)
VehicleTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 25)
VehicleTable.ColumnCount = 1
VehicleTable.ColumnStyles.add (RS_dotNetObject.columnStyleObject "percent" 100)
PrepareVehicleButton = RS_DotNetUI.InitButton "Prepare Vehicle"
dotNet.AddEventHandler PrepareVehicleButton "Click" PrepareVehicle
VehicleTable.Controls.Add PrepareVehicleButton 0 0
NukeMaterialsButton = RS_DotNetUI.InitButton "Nuke Materials"
dotNet.AddEventHandler NukeMaterialsButton "Click" NukeMaterials
VehicleTable.Controls.Add CutsceneDataPrepUI.NukeMaterialsButton 0 1
CutsceneDataPrepUI.Table.Controls.Add VehicleTable 0 2
tableHeight += (25 * 2)
)
3:
(
MapTable = dotNetObject "TableLayoutPanel"
MapTable.RowCount = 4
MapTable.Margin = dotNetObject "System.Windows.Forms.Padding" 2
MapTable.Dock = RS_dotNetPreset.DS_Fill
MapTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 25)
MapTable.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 25)
MapTable.ColumnCount = 1
MapTable.ColumnStyles.add (RS_dotNetObject.columnStyleObject "percent" 100)
EnvironmentSetupButton = RS_DotNetUI.InitButton "Environment Setup"
dotNet.AddEventHandler EnvironmentSetupButton "Click" SetupEnvironment
MapTable.Controls.Add EnvironmentSetupButton 0 0
PrepareMapButton = RS_DotNetUI.InitButton "Prepare Map"
dotNet.AddEventHandler PrepareMapButton "Click" PrepareMap
MapTable.Controls.Add PrepareMapButton 0 1
NukeMaterialsButton = RS_DotNetUI.InitButton "Nuke Materials"
dotNet.AddEventHandler NukeMaterialsButton "Click" NukeMaterials
MapTable.Controls.Add CutsceneDataPrepUI.NukeMaterialsButton 0 2
ShowCapturesButton = RS_DotNetUI.InitButton "Display Capture Spheres"
dotNet.AddEventHandler ShowCapturesButton "Click" CaptureDisplay
MapTable.Controls.Add CutsceneDataPrepUI.ShowCapturesButton 0 3
CutsceneDataPrepUI.Table.Controls.Add MapTable 0 2
tableHeight += (25 * 4)
)
)
CutsceneDataPrepUI.Form.Height = tableHeight
),
------------------------------------------------------------------------------------------------------------------------------------------
--UI
------------------------------------------------------------------------------------------------------------------------------------------
fn CreateUI =
(
RS_dotNetPreset.Font_Main = dotNetObject "System.Drawing.Font" "Futura" 10
-- form setup
Form = dotNetObject "maxCustomControls.maxForm"
Form.Text = "Materials Export Manager"
Form.StartPosition = (dotNetClass "System.Windows.Forms.FormStartPosition").manual
Form.Location = dotNetObject "system.drawing.point" 0 80
Form.MaximumSize = dotNetObject "System.Drawing.Size" 1600 1200
Form.MinimumSize = dotNetObject "System.Drawing.Size" 100 100
Form.FormBorderStyle = RS_dotNetPreset.FB_Sizable
dotNet.AddEventHandler Form "Load" FormOpen
dotNet.AddEventHandler Form "Closing" FormClose
--content
ToolTip = dotnetobject "ToolTip"
Table = dotNetObject "TableLayoutPanel"
Table.Dock = RS_dotNetPreset.DS_Fill
Table.RowCount = 3
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 40) --banner
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "absolute" 30) --dropdownlist
Table.RowStyles.add (RS_dotNetObject.rowStyleObject "percent" 100) --content
Table.ColumnCount = 1
Table.ColumnStyles.add (RS_dotNetObject.columnStyleObject "percent" 100)
Table.Margin = RS_dotNetPreset.Padding_None
Form.Controls.Add Table
RSBannerPanel = dotNetObject "System.Windows.Forms.Panel"
RSBannerPanel.borderstyle = RS_dotNetClass.borderStyleClass.FixedSingle
RSBannerPanel.dock = RS_dotNetPreset.DS.Fill
--local banner = makeRsBanner dn_Panel:RSBannerPanel width:395 studio:"london" mail:"andy.davis@rockstarlondon.com" wiki:"Map_Art_Tech"
local banner = makeRsBanner dn_Panel:RSBannerPanel width:395 studio:"london" filename:(getThisScriptFilename()) mail:"andy.davis@rockstarlondon.com" wiki:"Map_Art_Tech"
banner.setup()
Table.Controls.Add RSBannerPanel 0 0
ModeComboBox = dotNetObject "ComboBox"
ModeComboBox.Dock = RS_dotNetPreset.DS.Fill
ModeComboBox.DropDownStyle = ModeComboBox.DropDownStyle.DropDownList
ModeComboBox.Font = dotNetObject "System.Drawing.Font" "Futura" 11
modes = #("CHARACTER", "PROP", "VEHICLE", "MAP")
ModeComboBox.Items.AddRange modes
(dotnetclass "System.gc").SuppressFinalize ModeComboBox
(dotnetclass "System.gc").KeepAlive ModeComboBox
dotNet.AddEventHandler ModeComboBox "SelectedIndexChanged" UpdateTool
Table.Controls.Add ModeComboBox 0 1
----------------------------------------------------------------------------------------------------------------------------
--CHECKBOX TABLE
----------------------------------------------------------------------------------------------------------------------------
-- CheckBoxTable = dotNetObject "TableLayoutPanel"
-- CheckBoxTable.RowCount = 3
-- CheckBoxTable.Dock = RS_dotNetPreset.DS_Fill
-- CheckBoxTable.RowStyles.add (RS_dotNetObject.rowStyleObject "percent" 25)
-- CheckBoxTable.RowStyles.add (RS_dotNetObject.rowStyleObject "percent" 25)
-- CheckBoxTable.RowStyles.add (RS_dotNetObject.rowStyleObject "percent" 25)
-- CheckBoxTable.ColumnCount = 1
-- CheckBoxTable.ColumnStyles.add (RS_dotNetObject.columnStyleObject "percent" 100)
-- AlphaCheckBox = RS_dotNetUI.InitCheckBox "Include Alpha Maps"
-- CheckBoxTable.Controls.Add AlphaCheckBox 0 0
-- SpecularCheckBox = RS_dotNetUI.InitCheckBox "Include Specular Maps"
-- CheckBoxTable.Controls.Add SpecularCheckBox 0 1
-- NormalCheckBox = RS_dotNetUI.InitCheckBox "Include Normal Maps"
-- CheckBoxTable.Controls.Add NormalCheckBox 0 2
--draw form
Form.ShowModeless()
Form
)
)
if CutsceneDataPrepUI != undefined then
(
CutsceneDataPrepUI.Form.Close()
)
CutsceneDataPrepUI = CutsceneDataPrepUIStruct()
CutsceneDataPrepUI.CreateUI()
)
else
(
if theProject == "gta5" then
(
filein (theWildwest+"/script/3dsMax/Cutscene/cs_ResourcePrep_WPF.ms")
)
else
(
messagebox (theProject+" is not a configured project for this tool.\nPlease contact techArt.") beep:true title:"WARNING!"
)
)