Wednesday 27 October 2021

I fixed it.......for now

After putting the original script through the production pipeline I noticed a few errors. These had been fine when working off one max file, but once I used the loop to go through multiple max files the issues started to creep in. 
3DS Max stores variables once they are assigned and this is something I need to get used to when debugging. If I ran the script once and stepped through to solve an issue, any variables I had manually set during this would be locked in place till overwritten or Max was closed. This led to a variable not being set correctly in the loops and this only became apparent once I got the final results back, the files had rendered out correctly but not in the right folders. My first clue was that each image sequence was begin stored in the previous folder according o the order of the main loop.

The issue was with the render output filename and path, with the variable "verShotFolder" This variable was being set inside of an 'if' loop and not being stored outside of it afterwards. 
The solution was to create this variable at the beginning of the whole script as verShotFolder = ""

I also split some of that loop up as the...
if (doesfileexist verShotFolder) != true do
(makeDir verShotFolder)
...was being called the same no matter the result of the first loop.

----------------------------------------------------------------------------------------------------------------------

Debugging this code was a bit of a mission, but I feel I've learned a significant flag to watch out for in future coding exercises. If a variable from inside a loop is being called outside of it, that variable must be declared first, outside of the loop, so that the loop can fill it in, otherwise the variable from the loop will only hold the value assigned to it for the duration of the loop.

----------------------------------------------------------------------------------------------------------------------

maxFiles = getfiles @"O:\VirtualTour_VR\3D\Projects\Scenes\ScriptBackup\*.max"
::filein @"O:VirtualTour_VR\Scripts\DeadlineSubmitter_v01.ms"
mergeFileName = @"O:\VirtualTour_VR\3D\Projects\Scenes\ScriptTest\NovartisUpdatedHead01.max"
verShotFolder = ""
for i = 1 to maxFiles.count do
(
loadMaxFile (maxfiles[i])
verShotFolder = ""
---------------------------------------------------------------------------
----------- Update geo and texture

oldHeadGeo = $Char_Head
headParent = $Char_CTRL_Main
bandRemove = $Char_HeadStrip
innerHead = $Char_InnerHead

mergeMAXFile mergeFileName  #useMergedMtlDups
newHeadGeo = $NovartisUpdatedHead01
newHeadGeo.transform = oldHeadGeo.transform
newHeadGeo.parent = headParent
innerHead.parent = headParent
delete oldHeadGeo
delete bandRemove
viewport.setCamera $PhysCamera001
meditMaterials[1] = sceneMaterials["Head_Body"]
$Char_Body.material = meditMaterials[1]

---------------------------------------------------------------------------
----------- Make new folder for v2.2

renderSceneDialog.close()
rc=renderers.current
rc.output_saveRawFile=true
rendTimeType = 2
ogOutput = rc.output_rawFileName
verFolder = pathConfig.removePathLeaf ogOutput
verFolderTest = (filterstring (verFolder) "\\")[(filterstring (verFolder) "\\").count]

rendFileOuputSplit = (filterstring (ogOutput) "\\")[(filterstring (ogOutput) "\\").count]
versionUp =  (filterstring (rendFileOuputSplit) ".")
versionPt2 = versionUp[2]
versionPt2Solo = versionPt2[1] as integer
versionUpSolo = (versionPt2Solo + 1) as string
UppedVerFilename = versionUp[1] + "." + versionUpSolo + "_" + "." + versionUp[3]
--outputPath = verShotFolder + "\\" + UppedVerFilename

ogFileName = (filterstring (ogOutput) "\\")[(filterstring (ogOutput) "\\").count]
ogFileVerMain =  (filterstring (ogFileName) ".")[1]
mainVer = ogFileVerMain[ogFileVerMain.count]
targetVersion =  "v" + mainVer + "." + versionUpSolo
shotFolder = pathConfig.removePathLeaf verFolder
if (verFolderTest == "Intro") then
(
verShotFolder = (verFolder + "\\" + targetVersion)
)
else if (verFolderTest == "Outro") then
(
verShotFolder = (verFolder + "\\" + targetVersion)
)
else
(
verShotFolder = (shotFolder + "\\" + targetVersion)
)
if doesfileexist(verShotFolder) != true do
(
makeDir verShotFolder
)

---------- Set Vray render output to new version

outputPath = verShotFolder + "\\" + UppedVerFilename
rc.output_rawFileName = outputPath

---------- Save new max file version
maxFilePathSplit = (filterstring (maxfilepath) "\\")
parentMaxFolder = pathConfig.removePathLeaf maxfilepath
newMaxFileSave = parentMaxFolder
maxFileNameSplit =  (filterstring (maxfilename) ".")
maxFileVersion = maxFileNameSplit[2] as integer
maxFileVersioningUp = (maxFileVersion + 1) as string
newMaxFileName = maxFileNameSplit[1] + "." + maxFileVersioningUp + "." + maxFileNameSplit[3]
newMaxFileNameFullPath = maxfilepath + newMaxFileName
if (doesfileexist newMaxFileNameFullPath) != true then
(
saveMaxFile newMaxFileNameFullPath
)
else
(
messagebox "!!!Warning!!!\nA more recent max file already exists\nJob has been submitted anyway"
)

----------Send to deadline

_DlJobName = maxfilename
_Priority = 30
_Comment = "-- Submitted Via DLSubmitJob"
_UserName = "Eoin"
_Group = "singles"
DLRenSubmit _DlJobName _Priority _Comment _UserName _Group 
)



Wednesday 13 October 2021

Pipeline Beginnings

 I've been learning to code over the past few years but have recently started a course "TD Certification" by Allan Mckay. I've decided to track my progress here so will be posting up any scripts I work on for work and anything else I can think to script.

----------------------------------------------------------------------------------------------------------------------

I've found in the past that I have struggled to find applications for the coding I was learning, but as a result of this course I feel I now have enough knowledge, and the ability to plan out a script. I had always found blank page syndrome difficult to deal with in relation to coding, never really knowing what could be done and how to go about it. Through the course I have found out that the easiest way is to break any job up into single steps and then work on each one of those one by one, combining them where needed. The course began focusing on Maxscript but towards the end we have moved on to Python, where I would have a small amount of experience which I am now finding I have a greater understanding than i thought I did beforehand.

----------------------------------------------------------------------------------------------------------------------

At the bottom of this post is the code for the first situation I have found where I can apply what I have learned to a task at work - I needed to replace geometry and update a texture for 15 files and then submit each one to Deadline with a versioned up folder and file name. Below is the plan I came up with to get myself started.

1.Import new head
2.Extract new texture
3.Apply new texture to body
4.Align new head to old one
5.Attach head to 'Char_CTRL_Main'
6.Remove old head and band
7.Version up render output
8.Turn render on
9.Make sure correct viewport is rendering
10.Save new max file
        11.Send to farm

While going through these steps I realised I could skip step 2 by bringing the new texture and setting a flag <#useMergedMtlDups> on the import function to specify to use the updated merged material instead of the scene one. EDIT: this unfortunately did not work as planned at which point I figured out how to transfer a texture from the imported geo to the rest of the geo in the scene that needed it to be applied on.

At the beginning of this exercise I had to pipe certain text items directly in, mainly around the version number for the max files and render outputs, but as I progressed I figured out some ways to extract these with code, thus allowing for the script to be used beyond 'v2.1'.
At present the only things that need to be entered manually are the location of the max files folder, and the assets that need to be replaced and/or deleted.

I really enjoyed this exercise, it was a great excuse to test out what I've learned over the last 2 months, both in terms of knowledge and how to go about building a script. Plenty of Google searching and testing single lines of code, but the satisfaction of getting something like this to work is hard to put to words.

----------------------------------------------------------------------------------------------------------------------

I am hoping I will get some more jobs that will allow me to push myself further, and I have some plans for a studio pipeline overhaul, to change the folder and file naming structure to allow for much greater automation of simple tasks.

----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------

maxFiles = getfiles @"O:\VirtualTour_VR\3D\Projects\Scenes\*.max"
for i = 1 to maxFiles.count do
(
loadMaxFile (maxfiles[i])

::filein @"O:\VirtualTour_VR\Scripts\DeadlineSubmitter_v01.ms"
mergeFileName =  
        @"O:\VirtualTour_VR\3D\Projects\Scenes\ScriptTest\CharUpdatedHead01.max"

---------------------------------------------------------------------------
----------- Update geo and texture

oldHeadGeo = $Char_Head
headParent = $Char_CTRL_Main
bandRemove = $Char_HeadStrip
innerHead = $Char_InnerHead


mergeMAXFile mergeFileName  #useMergedMtlDups
newHeadGeo = $UpdatedHead01
newHeadGeo.transform = oldHeadGeo.transform
newHeadGeo.parent = headParent
innerHead.parent = headParent

delete oldHeadGeo
delete bandRemove

        meditMaterials[1] = sceneMaterials["Head_Body"]
        $Char_Body.material = meditMaterials[1]

viewport.setCamera $PhysCamera001

---------------------------------------------------------------------------
----------- Make new folder and rename output path

        renderSceneDialog.close() rc=renderers.current rc.output_saveRawFile=true rendTimeType = 2 ogOutput = rc.output_rawFileName verFolder = pathConfig.removePathLeaf ogOutput verFolderTest = (filterstring (verFolder) "\\")[(filterstring (verFolder) "\\").count] rendFileOuputSplit = (filterstring (ogOutput) "\\")[(filterstring (ogOutput) "\\").count] versionUp = (filterstring (rendFileOuputSplit) ".") versionPt2 = versionUp[2] versionPt2Solo = versionPt2[1] as integer versionUpSolo = (versionPt2Solo + 1) as string UppedVerFilename = versionUp[1] + "." + versionUpSolo + "_" + "." + versionUp[3] outputPath = verShotFolder + "\\" + UppedVerFilename ogFileName = (filterstring (ogOutput) "\\")[(filterstring (ogOutput) "\\").count] ogFileVerMain = (filterstring (ogFileName) ".")[1] mainVer = ogFileVerMain[ogFileVerMain.count] targetVersion = "v" + mainVer + "." + versionUpSolo if (verFolderTest == "Intro") or (verFolderTest == "Outro") then ( verShotFolder = (verFolder + "\\" + targetVersion) if doesfileexist(verShotFolder) != true do ( makeDir verShotFolder ) ) else ( shotFolder = pathConfig.removePathLeaf verFolder verShotFolder = (shotFolder + "\\" + targetVersion) if doesfileexist(verShotFolder) != true do ( makeDir verShotFolder ) ) 
rc.output_rawFileName = outputPath


---------- Save new max file version

maxFilePathSplit = (filterstring (maxfilepath) "\\")
parentMaxFolder = pathConfig.removePathLeaf maxfilepath
newMaxFileSave = parentMaxFolder

maxFileNameSplit =  (filterstring (maxfilename) ".")
maxFileVersion = maxFileNameSplit[2] as integer
maxFileVersioningUp = (maxFileVersion + 1) as string
newMaxFileName = maxFileNameSplit[1] + "." + maxFileVersioningUp + "." +                                    maxFileNameSplit[3]
newMaxFileNameFullPath = maxfilepath + newMaxFileName
if (doesfileexist newMaxFileNameFullPath) != true then
(
saveMaxFile newMaxFileNameFullPath
)
else
(
messagebox "!!!Warning!!!\nA more recent max file already exists\nJob has been submitted            anyway"
)
----------Send to deadline

DLRenSubmit _JobName _Priority _Comment _UserName _Group 

)