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

802 lines
21 KiB
Plaintext
Executable File

filein (RsConfigGetWildWestDir() + "script/3dsMax/_config_files/Wildwest_header.ms") --wildwest header
filein (RsConfigGetWildWestDir() + "script/3dsMax/_common_functions/FN_VertexPaint.ms")
filein (RsConfigGetWildWestDir() + "script/3dsMax/_common_functions/FN_RSTA_Rigging.ms")
struct RsVeh_ChanBlueBakeStruct
(
id,
name,
channels
)
--/////////////////////////////////////////
-- UI
--/////////////////////////////////////////
try(destroyDialog VehicleBlueBakeUI)catch()
rollout VehicleBlueBakeUI "Vehicle Burn Bake" width:200 height:350
(
--/////////////////////////////////////////
-- VARIABLES
--/////////////////////////////////////////
local cascade = true
local ng = false
local mapChannelList = #((RsVeh_ChanBlueBakeStruct id:-2 name:"Alpha" channels:"all"),
(RsVeh_ChanBlueBakeStruct id:-1 name:"Illum" channels:"all"),
(RsVeh_ChanBlueBakeStruct id:0 name:"Color" channels:"all"),
(RsVeh_ChanBlueBakeStruct id:0 name:"Burn" channels:"b"))
local burnChannel = 0
local channels = "b"
local selectedChannel = mapChannelList[3]
--/////////////////////////////////////////
-- CONTROLS
--/////////////////////////////////////////
dotNetControl rsBannerPanel "Panel" pos:[0,0] height:32 width:VehicleBlueBakeUI.width
local banner = makeRsBanner dn_Panel:rsBannerPanel wiki:"CHANGEME" versionNum:1.22 versionName:"Suede Blues" filename:(getThisScriptFilename())
group "HD -> NG"
(
listbox lstChannel "Channel" height:4 items:(for item in mapChannelList collect item.name)
checkbox chkAllChannels "All"
button btnCopyMapData "Copy Map Data" width:155
edittext edtProcess text:"Ready" enabled:False
)
group ""
(
spinner spnSRCChannel "Source Channel" range:[-2, 99, 14] type:#integer width:65 align:#left
checkbox chkMultisample "Multi Sample" checked:true
--checkbox chkCascadeLOD "LOD Cascade" checked:true
)
button btnRestoreBlue "Restore Blue" width:165
button btnPushVCBlue "Push to VC Blue" width:165
progressBar prgProcess color:green
--/////////////////////////////////////////
-- FUNCTIONS
--/////////////////////////////////////////
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn updateProcessText msg =
(
edtProcess.text = msg
windows.processPostedMessages()
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn getVeh_Meshes theNode =
(
local selKids = RSTA_GetAllChildren theNode
(for item in selKids where GetAttrClass item == "Gta Object" collect item)
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn checkSelection =
(
local theNode = selection[1]
if theNode == undefined then return undefined
--check selection is valid, should be a helper with chassis child object
if theNode.children.count == 0 then
(
Messagebox "Please pick the vehicle hierarchy root helper" title:"Bad Selection"
return undefined
)
if matchpattern theNode.children[1].name pattern:"chassis*" == false then
(
Messagebox "Please pick the vehicle hierarchy root helper" title:"Bad Selection"
return undefined
)
--is it a nextgen asset
if ( matchpattern theNode.name pattern:"*_ng" ) do ng = true
theNode
)
-----------------------------------------------------------------------------------------------------------------------------------
mapped fn CpvFlushChannel obj mapChannel: colour:[1,1,1] =
(
if(mapChannel == unsupplied) then
(
return false
)
local setMapVert = meshop.setMapVert
convertToMesh obj
if (not (meshop.getMapSupport obj mapChannel)) then
(
meshop.setMapSupport obj mapChannel true
)
for mv=1 to (meshop.getNumMapVerts obj mapChannel) do
(
setMapVert obj mapChannel mv colour
)
return true
)
/***
***/
fn checkMapChannelSupport targetMesh mapChannel enableSupport:True =
(
local GetMapSupport
local GetNumMaps
local SetNumMaps
local SetMapSupport
if (classOf targetMesh == Editable_Poly) or (classOf targetMesh == PolyMeshObject) then
(
GetMapSupport = polyop.getMapSupport
GetNumMaps = polyop.getNumMaps
SetNumMaps = polyop.setNumMaps
SetMapSupport = polyop.setMapSupport
)
if (classOf targetMesh == Editable_Mesh) then
(
GetMapSupport = meshop.getMapSupport
GetNumMaps = meshop.getNumMaps
SetNumMaps = meshop.setNumMaps
SetMapSupport = meshop.setMapSupport
)
if (GetMapSupport targetMesh mapChannel == false) then
(
--print "missing map channel"
local numChannels = GetNumMaps targetMesh
if numChannels < (mapChannel + 1) then
(
SetNumMaps targetMesh (mapChannel + 1)
)
SetMapSupport targetMesh mapChannel true
)
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn combineLODPieces pieces =
(
local materialCopy = copy pieces[1].material
copies = for obj in pieces collect copy obj
for obj in copies do
(
convertToMesh obj
obj.material = materialCopy
)
for v=2 to copies.count do attach copies[1] copies[v]
copies[1].material = originalMaterial
copies[1]
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn buildObjectList theNode &veh_LODChain =
(
--build object lists for each lod level
append veh_LODChain (getVeh_Meshes theNode)
local LODLevels = undefined
if ng then
(
local theNodeName = (filterString theNode.name "_")[1]
if (theNodeName != undefined) do
(
LODLevels = execute ("$" + theNodeName + "*")
--append veh_LODChain (getVeh_Meshes theNode)
local HDNode = getNodeByName theNodeName
if (HDNode != undefined) do
(
append veh_LODChain (getVeh_Meshes HDNode)
for i=1 to LODLevels.count do
(
local LODNodeName = getNodeByName (theNodeName + "_l" + (i as String))
if LODNodeName != undefined then append veh_LODChain (getVeh_Meshes LODNodeName)
)
)
)
)
else
(
LODLevels = execute ("$" + theNode.name + "*")
for i=1 to LODLevels.count do
(
local theNodeName = getNodeByName (theNode.name + "_l" + (i as String))
if theNodeName != undefined then append veh_LODChain (getVeh_Meshes theNodeName)
)
)
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn restoreBlue =
(
local theNode = checkSelection()
if ( theNode == undefined ) then ( return false )
--build object lists for each lod level
local veh_LODChain = #()
buildObjectList theNode &veh_LODChain
/*
append veh_LODChain (getVeh_Meshes theNode)
local LODLevels = execute ("$" + theNode.name + "*")
for i=1 to LODLevels.count do
(
local theNodeName = getNodeByName (theNode.name + "_l" + (i as String))
if theNodeName != undefined then append veh_LODChain (getVeh_Meshes theNodeName)
)
*/
--Go to the start frame (for skinning information)
Max Time Start
--Save any skinning information
SkinnedObjList = #()
for sub_LODChain in veh_LODChain do
(
for obj in sub_LODChain do
(
if( isMeshSkinned obj ) then
(
--record object and type
append SkinnedObjList (datapair Obj:obj Class:(classof obj.BaseObject))
--Output skinned data
::boneList = #()
outputSkinningData obj
--Collapse object down
collapseStack obj
)
)
)
prgProcess.value = 0
for l=1 to veh_LODChain.count do
(
for obj in veh_LODChain[l] do
(
ChannelInfo.copySubChannel obj 3 0 0 --red channel
ChannelInfo.pasteSubChannel obj 3 0 2 --blue channel
collapseStack obj
)
prgProcess.value = (100.0 * (l as float / veh_LODChain.count))
)
--Push skinning information back
for SkinnedObj in SkinnedObjList do
(
if( classof SkinnedObj.Obj != SkinnedObj.Class ) then
(
convertTo SkinnedObj.Obj SkinnedObj.Class
)
--Write data back skinned data
InputSkinningData SkinnedObj.Obj
)
prgProcess.value = 0
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn blueBakeProcess =
(
local theNode = checkSelection()
if ( theNode == undefined ) then ( return false )
prgProcess.value = 0
--build object lists for each lod level
local veh_LODChain = #()
append veh_LODChain (getVeh_Meshes theNode)
local HDCount = veh_LODChain.count
local LODLevels = execute ("$" + theNode.name + "*")
for i=1 to (LODLevels.count - 1) do
(
local theNodeName = getNodeByName (theNode.name + "_l" + (i as String))
if (theNodeName != undefined) then
(
append veh_LODChain (getVeh_Meshes theNodeName)
)
)
local justHD = false
if(veh_LODChain.count == HDCount) then --we have no lods so just transfer to itself
(
justHD = true
)
local veh_Name = theNode.name
local veh_LOD = 0
local UI_SRCChannel = spnSRCChannel.value
--local cascade = chkCascadeLOD.state
--Go to the start frame (for skinning information)
Max Time Start
--Save any skinning information
SkinnedObjList = #()
for sub_LODChain in veh_LODChain do
(
for obj in sub_LODChain do
(
if( isMeshSkinned obj ) then
(
--record object and type
append SkinnedObjList (datapair Obj:obj Class:(classof obj.BaseObject))
--Output skinned data
::boneList = #()
outputSkinningData obj
--Collapse object down
collapseStack obj
)
)
)
--If justHD then we're just transferrring channel data between itself
if justHD then
(
for item in veh_LODChain[1] do
(
RsProjectVertexMap item item SRCchannel:UI_SRCChannel TGTchannel:burnChannel subChannels:channels sampleBomb:false preserveMods:false --pushVal:0.01
)
)
else --Projecting to LOD chanin levels
(
local penultimateLOD = (veh_LODChain.count - 1)
for v=1 to penultimateLOD do
(
prgProcess.value = (100.0 * (v as float / penultimateLOD))
local veh_Meshes = veh_LODChain[v]
if (v == penultimateLOD) then
(
--copy the lod geo
copyLOD = combineLODPieces veh_LODChain[v]
--move it to the lastLOD pos
copyLOD.pos = veh_LODChain[v+1][1].pos
--do the bake down
for item in veh_LODChain[v+1] where (GetAttrClass item == "Gta Object") do
(
CpvFlushChannel item mapChannel:burnChannel
RsProjectVertexMap copyLOD item SRCchannel:UI_SRCChannel TGTchannel:burnChannel subChannels:channels sampleBomb:chkMultisample.checked preserveMods:false pushVal:0.01
)
--delete the copy
delete copyLOD
)
else
(
for item in veh_Meshes where (GetAttrClass item == "Gta Object") do
(
local nextLODList = veh_LODChain[v+1]
local LODIdx
if v == 1 then
(
LODIdx = for idx=1 to nextLODList.count where (MatchPattern nextLODList[idx].name pattern:(item.name+"_l1") == true) collect idx
)
else
(
local itemName = substring item.name 1 (item.name.count - 3)
LODIdx = for idx=1 to nextLODList.count where (MatchPattern nextLODList[idx].name pattern:(itemName+"_l"+(v as String)) == true) collect idx
)
if LODIdx.count > 1 then print LODIdx
if LODIdx.count == 0 then
(
continue
)
LODIdx = LODIdx[1]
LODNode = veh_LODChain[v+1][LODIdx]
format "source:% lod:%\n" item.name LODNode.name
--get the node and check it exists
if (not isValidNode LODNode) then
(
print "bad node"
continue
)
--move the next lower LOD mesh for this into the same position
local originalLODPos = LODNode.pos
LODNode.pos = item.pos
--do the bake down
local success
if (v == 1) then
(
checkMapChannelSupport item burnChannel
--CpvFlushChannel LODNode mapChannel:burnChannel
RsProjectVertexMap item item SRCchannel:UI_SRCChannel TGTchannel:burnChannel subChannels:channels sampleBomb:false preserveMods:false showMessages:false
success = RsProjectVertexMap item LODNode SRCchannel:UI_SRCChannel TGTchannel:burnChannel subChannels:channels sampleBomb:chkMultisample.checked pushVal:0.01 preserveMods:false
)
else --copy cpv across
(
--CpvFlushChannel LODNode mapChannel:burnChannel
success = RsProjectVertexMap item LODNode SRCchannel:burnChannel TGTchannel:burnChannel subChannels:channels sampleBomb:chkMultisample.checked pushVal:0.01 preserveMods:false
)
if success != ok then
(
print (item.name + " missing map channel " + UI_SRCChannel as String)
--LODNode.pos = originalLODPos
--return false
)
LODNode.pos = originalLODPos
)
)
windows.processPostedMessages()
)
)
--Push skinning information back
for SkinnedObj in SkinnedObjList do
(
if( classof SkinnedObj.Obj != SkinnedObj.Class ) then
(
convertTo SkinnedObj.Obj SkinnedObj.Class
)
--Write data back skinned data
InputSkinningData SkinnedObj.Obj
)
prgProcess.value = 0
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
fn blueBakeProcessNG =
(
local theNode = checkSelection()
if ( theNode == undefined ) then ( return false )
prgProcess.value = 0
--build object lists for each lod level
local veh_LODChain = #()
buildObjectList theNode &veh_LODChain
local veh_Name = theNode.name
local veh_LOD = 0
local UI_SRCChannel = spnSRCChannel.value
--local cascade = chkCascadeLOD.state
--Go to the start frame (for skinning information)
Max Time Start
--Save any skinning information
SkinnedObjList = #()
for sub_LODChain in veh_LODChain do
(
for obj in sub_LODChain do
(
if( isMeshSkinned obj ) then
(
--record object and type
append SkinnedObjList (datapair Obj:obj Class:(classof obj.BaseObject))
--Output skinned data
::boneList = #()
outputSkinningData obj
--Collapse object down
collapseStack obj
)
)
)
format "veh_LODChain: % \n" veh_LODChain
if(veh_LODChain.count == 1) then --just transfer onto itself
(
for item in veh_LODChain[1] do
(
RsProjectVertexMap item item SRCchannel:UI_SRCChannel TGTchannel:burnChannel subChannels:channels sampleBomb:false preserveMods:false --pushVal:0.01
)
)
else
(
--First copy from burn channels specified in the UI to vertexcolour channel specified by channels
for item in veh_LODChain[1] do
(
RsProjectVertexMap item item SRCchannel:UI_SRCChannel TGTchannel:burnChannel subChannels:channels sampleBomb:false preserveMods:false --pushVal:0.01
)
local penultimateLOD = (veh_LODChain.count - 1)
for v=1 to penultimateLOD do
(
prgProcess.value = (100.0 * (v as float / penultimateLOD))
local veh_Meshes = veh_LODChain[v]
--copy the lod geo
copyLOD = combineLODPieces veh_LODChain[v]
--move it to the lastLOD pos
copyLOD.pos = veh_LODChain[v+1][1].pos
--do the bake down
for item in veh_LODChain[v+1] where GetAttrClass item == "Gta Object" do
(
RsProjectVertexMap copyLOD item SRCchannel:burnChannel TGTchannel:burnChannel subChannels:channels sampleBomb:chkMultisample.checked pushVal:0.01 preserveMods:false
)
--delete the copy
delete copyLOD
)
)
--Push skinning information back
for SkinnedObj in SkinnedObjList do
(
if( classof SkinnedObj.Obj != SkinnedObj.Class ) then
(
convertTo SkinnedObj.Obj SkinnedObj.Class
)
--Write data back skinned data
InputSkinningData SkinnedObj.Obj
)
prgProcess.value = 0
)
/***
Copy the map channel data between HD and NG vehicle hierarchies
***/
fn TakeMaxSample samples =
(
fn compare v1 v2 =
(
local l1 = length v1
local l2 = length v2
case of
(
(l1 > l2): 1
(l1 < l2): -1
default:0
)
)
qsort samples compare
samples[1]
)
fn copyHDtoNG source fromMapChannel:0 toMapChannel:0 subChannels:"all" =
(
--get the HD objects
local HDMeshes = getVeh_Meshes source
--get the NG objects
local NGRoot = getNodeByName (source.name + "_ng")
local NGMeshes = getVeh_Meshes NGRoot
local NGMeshNames = for item in NGMeshes collect item.name
--move the HD vehicle to the NG vehicle pos
local originalPos = NGRoot.pos
NGRoot.pos = source.pos
if (HDMeshes.count != NGMeshes.count) then
(
print "HD NG mesh count mismatch!"
)
--Process the meshes
updateProcessText ("Processing channel: " + (fromMapChannel as String))
mainProgress = RSProgressWindow Title:"Copy Channel ....." StartStep:1 EndStep:HDMeshes.count
mainProgress.Start()
try
(
cui.commandPanelOpen = false
prgProcess.value = 10
for i = 1 to HDMeshes.count do
(
local NGMeshName = (HDMeshes[i].name + "_ng")
local NGMeshIndex = findItem NGMeshNames NGMeshName
if (NGMeshIndex == 0) then
(
format "Woah! cant find a valid index into NGMeshes"
messageBox ("Cant find: " + NGMeshName) title:"Error: Missing Mesh"
NGRoot.pos = originalPos
--prgProcess.value = 0
mainProgress.End()
updateProcessText "Ready"
return false
)
--check for any skin modifiers
local NGMeshHasSkin = false
if (NGMeshes[NGMeshIndex].modifiers.count == 1) and (isKindOf NGMeshes[NGMeshIndex].modifiers[1] Skin) then
(
NGMeshHasSkin = true
RSTA_outputSkinWeightData NGMeshes[NGMeshIndex]
deleteModifier NGMeshes[NGMeshIndex] 1
)
--flush the channel
CpvFlushChannel NGMeshes[NGMeshIndex] mapChannel:toMapChannel
--project verts
-- print HDMeshes[i].name
RsProjectVertexMap HDMeshes[i] NGMeshes[NGMeshIndex] SRCchannel:fromMapChannel TGTchannel:toMapChannel subChannels:subChannels sampleBomb:true pushVal:0.01 preserveMods:false --samplingFn:TakeMaxSample
if NGMeshHasSkin then
(
addModifier NGMeshes[NGMeshIndex] (Skin())
RSTA_inputSkinData NGMeshes[NGMeshIndex]
NGMeshHasSkin = false
)
--prgProcess.value = (100.0 * (i / (HDMeshes.count as float)))
mainProgress.PostProgressStep()
windows.processPostedMessages()
)
cui.commandPanelOpen = true
)
catch
(
print "there was a crash"
cui.commandPanelOpen = true
mainProgress.End()
-- --restore position
-- print "***************Catch Error!*****************"
NGRoot.pos = originalPos
-- prgProcess.value = 0
-- updateProcessText "Ready"
)
--reset progress
--prgProcess.value = 0
mainProgress.End()
updateProcessText "Ready"
--restore position
NGRoot.pos = originalPos
redrawViews()
)
--/////////////////////////////////////////
-- EVENTS
--/////////////////////////////////////////
--/////////////////////////////////////////
--
--/////////////////////////////////////////
on btnCopyMapData pressed do
(
--check selection
local selectedNode = checkSelection()
--print selectedNode
if (selectedNode == undefined) do
(
return false
)
if ((MatchPattern selectedNode.name pattern:"*_ng") == true) do
(
messageBox "Choose the HD vehicle root" title:"Bad Selection"
return false
)
--do the deed
updateProcessText "Working.."
if chkAllChannels.state then
(
for item in mapChannelList do
(
local channelIdx = item.id
copyHDtoNG selectedNode fromMapChannel:channelIdx toMapChannel:channelIdx subChannels:item.channels
)
)
else
(
copyHDtoNG selectedNode fromMapChannel:selectedChannel.id toMapChannel:selectedChannel.id subChannels:selectedChannel.channels
)
updateProcessText "Ready"
)
--/////////////////////////////////////////
-- Restore blue channel event
--/////////////////////////////////////////
on btnRestoreBlue pressed do
(
restoreBlue()
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
on btnPushVCBlue pressed do
(
checkSelection()
if ng then
(
blueBakeProcessNG()
)
else
(
blueBakeProcess()
)
)
on lstChannel selected item do
(
selectedChannel = mapChannelList[item]
print mapChannelList[item].id
)
--/////////////////////////////////////////
--
--/////////////////////////////////////////
on VehicleBlueBakeUI open do
(
banner.setup()
lstChannel.selection = 3
)
)
createDialog VehicleBlueBakeUI
RsGetLodChildren $