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

334 lines
10 KiB
Plaintext
Executable File

--setup scene geo for lighting
--url:bugstar:446769
filein (RsConfigGetWildWestDir() + "script/3dsMax/_config_files/Wildwest_header.ms")
filein (RsConfigGetToolsDir()+"dcc/current/max2012/scripts/rockstar/util/scenebaker/nightLightUtils.ms")
try( DestroyDialog mapBakeGeoSetup_UI)catch()
rollout mapBakeGeoSetup_UI "Map Bake Block Setup"
(
--/////////////////////////////////////////////////////////////////
-- VARS
--/////////////////////////////////////////////////////////////////
local blockNeighboursCSV = RsConfigGetToolsDir() + "etc/config/generic/Block_Neighbours_for_lighting.csv"
local regex = dotnetclass "System.Text.RegularExpressions.Regex"
local re_IgnoreCase = (dotnetclass "System.Text.RegularExpressions.RegexOptions").IgnoreCase
local blockNeighbours = dotNetObject "RSG.MaxUtils.MaxDictionary"
local mapContainers = (RsConfigGetArtDir() + "Models")
local standardMat = StandardMaterial()
local lightingModelLayer = LayerManager.getLayerFromName "LightingModel"
--/////////////////////////////////////////////////////////////////
-- UI CONTROLS
--/////////////////////////////////////////////////////////////////
button btn_doSetup "Setup" width:475
listbox lst_Process width:475 height:15
progressbar prg_Process color:green
--/////////////////////////////////////////////////////////////////
-- FUNCTIONS
--/////////////////////////////////////////////////////////////////
fn notifyProcess inText =
(
--get the text array
theText = lst_Process.items
--append the new item
append theText inText
--stuff back into the control
lst_Process.items = theText
--select last item
lst_Process.selection = theText.count
windows.processPostedMessages()
)
fn getPrimaryContainerName =
(
--get scene containers
loadedContainers = for obj in $objects where classOf obj == container collect obj
if loadedContainers.count == 0 then
(
messagebox "No containers in the scene, exiting" title:"Error"
return false
)
if loadedContainers.count > 1 then
(
messageBox "There is more than 1 container present" title:"huh?"
return false
)
loadedContainers[1].name
)
fn mapBakeGeoSetup =
(
--create a lightingmodel layer if it doesnt exist
notifyProcess "Creating lighting model layer"
if LayerManager.getLayerFromName "LightingModel" == undefined then
(
lightingModelLayer = LayerManager.newLayerFromName "LightingModel"
)
--load each container and process the relevant contents
files = getDepotFiles mapContainers wildcard:"*.maxc" walk:true
if files.count == 0 then
(
messageBox "Cant retrieve filenames from p4" title:"ERROR"
try( DestroyDialog mapBakeGeoSetup_UI)catch()
return false
)
--The current scene container
rootBlockName = getPrimaryContainerName()
if rootBlockName == false then return false
lightingModelName = rootBlockName + "_Lighting_Model"
primaryContainer = getNodeByName rootBlockName
--open the container
--primaryContainer.setOpen true
--delete any old lighting model
try( delete (getNodeByname lightingModelName))catch()
--retrieve the neighbours
blockNeighbours.TryGetValue rootBlockName &neighbours
format "neighbours: %\n" neighbours
--reset progress
prg_Process.value = 0
prgStep = 100.0 / neighbours.count
--print files
lightingMeshes = #()
roadPropHitList = #()
roadPropContainers = #()
step = 1
notifyProcess "Processing neighbouring blocks.."
for blockName in neighbours do
(
notifyProcess blockName
--find the container path
containerPath = (for item in files where (getFileNameFile item.depotFile) == blockName collect item.depotFile)[1]
if containerPath != undefined then
(
--if this is a road container then we need to load the prop file for it to get the lights setup for the nightbake
isRoad = false
if regex.isMatch blockName "rd|fwy?" re_IgnoreCase != false then --we have a road container, find the prop files for it
(
isRoad = true
notifyProcess "This is a road container.."
--match against files in the same folder
containerDir = (dotnetclass "System.IO.Path").getDirectoryName containerPath
containerDir = substituteString containerDir "\\" "/"
areaFiles = getDepotFiles containerDir wildcard:".maxc" walk:true
areaContainers = for f in areaFiles collect f.depotfile
for item in areaContainers where regex.isMatch item "(rd([0-9])?_props.maxc)|(fwy_0[0-9]_props.maxc)" re_IgnoreCase != false do
(
notifyProcess ("Load road prop file:" + item)
--check if its already been hit
if finditem roadPropHitList item == 0 then
(
append roadPropHitList item
format "roadProps: % \n" item
--propTainer = roadMatches.item[r].value
--getPropLights item
--sync the container
gRsPerforce.p4.run "sync" #(item)
localPath = substituteString item "//depot" "x:"
roadPropContainer = Containers.CreateInheritedContainer localPath
roadPropContainer.makeUnique()
--add to list
append roadPropContainers roadPropContainer
)
)
)
--also we want the LOD from the road not the SLOD
---------------------------------------
--sync the file and on we go
gRsPerforce.p4.run "sync" #(containerPath)
--get local path
adjBlockLocalPath = substituteString containerPath "//depot" "x:"
--check we did get the file locally
if doesFileExist adjBlockLocalPath == false then continue
print containerPath
--load the container
notifyProcess "Loading container"
theContainer = Containers.CreateInheritedContainer adjBlockLocalPath
theContainer.MakeUnique()
--id the LODS
notifyProcess "Extracting LODS"
LODS = undefined
if isRoad then
(
LODS = for obj in theContainer.children where matchPattern obj.name pattern:"*_LOD*" == true collect obj
)
else
(
LODS = for obj in theContainer.children where matchPattern obj.name pattern:"*_SLOD*" == true collect obj
)
--print SLODS
--apply to SLODS and detach from parent container
--merge the meshes
--
for obj in LODS do
(
obj.material = standardMat
obj.parent = undefined
)
--add to the list
join lightingMeshes LODS
--delete the container
delete theContainer
--update progress
prg_Process.value = step * prgStep
step += 1
)
)
--print lightingMeshes
--merge all the lighting meshes together
notifyProcess "Process resulting light model"
combinedMesh = convertToPoly lightingMeshes[1]
for i = 2 to lightingMeshes.count do
(
attachee = convertToPoly lightingMeshes[i]
polyop.attach lightingMeshes[1] attachee
)
--rename the object
combinedMesh.name = lightingModelName
--set to not export
attrID = getAttrIndex "Gta Object" "Dont Export"
setAttr combinedMesh attrID false
--add to lighting layer
theLayer = LayerManager.getLayerFromName "LightingModel"
theLayer.addNode combinedMesh
--add to the primary container
--primaryContainer.setOpen true
primaryContainer.AddNodeToContent combinedMesh
--primaryContainer.setOpen false
--create the lights
notifyProcess "Creating lights"
RsRefFuncs.loadRSrefData()
print "create nightlights"
nightLightUtils.loadLightConfig()
nightLightUtils.generatePhotoLights()
--add them to the lighting layer
for nightLight in nightLightUtils.createdLights do
(
theLayer.addNode nightLight
primaryContainer.AddNodeToContent nightLight
)
--break()
for cont in roadPropContainers do
(
format "Deleting roadPropContainer: % \n" cont
delete cont
)
--delete roadPropContainer
--reset progress bar
prg_Process.value = 0
notifyProcess "Finished!"
)
fn processBlockNeighboursCSV row =
(
bits = (dotNetObject "System.String" row).split ","
--check first item is a valid block name
--if it doesnt have an underscore in the name
matches = regex.matches bits[1] "\w\w[0-9]+_.+" re_IgnoreCase
if matches.count != 0 then
(
containerName = matches.item[0].value
if containerName != undefined then
(
neighbours = for item = 2 to bits.count where bits[item] != "" collect bits[item]
--set dict
key = trimright bits[1]
blockNeighbours.add key neighbours
)
)
)
--/////////////////////////////////////////////////////////////////
-- EVENTS dear boy
--/////////////////////////////////////////////////////////////////
on btn_doSetup pressed do
(
primaryContainerName = getPrimaryContainerName()
if primaryContainerName == false then return false
lightingModelName = primaryContainerName + "_Lighting_Model"
--check for existing mesh and prompt to replace it if it exists
lightingModelLayer = LayerManager.getLayerFromName "LightingModel"
if lightingModelLayer != undefined then
(
success = lightingModelLayer.nodes &layerNodes
lightingModel = undefined
if success then
(
lightingModel = for obj in layerNodes where obj.name == lightingModelName collect obj.name
)
if lightingModel.count != 0 then
(
decision = queryBox "Do you want to regenerate the lighting model for this container?" title:"Regenerate?"
if decision == true then
(
--generate lighting model
mapBakeGeoSetup()
)
)
else
(
mapBakeGeoSetup()
)
)
else --starting with a clean scene
(
mapBakeGeoSetup()
)
)
on mapBakeGeoSetup_UI open do
(
--parse block neighbour file and generate map
csv = CSVReader()
csv.csvFile = blockNeighboursCSV
csv.processingFn = processBlockNeighboursCSV
csv.open()
csv.close()
--print blockNeighbours.keys
)
)
createDialog mapBakeGeoSetup_UI width:500 height:275 style:#(#style_titlebar, #style_border, #style_sysmenu, #style_minimizebox)