3905 lines
113 KiB
Plaintext
Executable File
3905 lines
113 KiB
Plaintext
Executable File
escapeenable = true
|
|
|
|
-- tool to read in 3Lateral xml files to regenerate facial expressions
|
|
--June 11
|
|
--Matt Rennie
|
|
|
|
|
|
-- fbx import settings need to be add and units set to cm
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
-- This line loads the custom header
|
|
filein (RsConfigGetWildWestDir() + "script/3dsMax/_config_files/Wildwest_header.ms")
|
|
RsCollectToolUsageData (getThisScriptFilename())
|
|
|
|
|
|
-- Light settings are stored in a config file. Load the vertex and light settings required for the tool
|
|
vbakesettings = pathToConfigFiles + "general/max_vertex_bake_settings.dat"
|
|
try (filein vbakesettings) catch (messagebox ("Couldn't find project specific light settings file. \r\nWas expecting " + vbakesettings ))
|
|
|
|
|
|
filein "rockstar/export/settings.ms" -- This is fast
|
|
|
|
-- RsCollectToolUsageData (getThisScriptFilename())
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
global vtxWeight = 4
|
|
contin = true --hack to try and ensure valid exit
|
|
objName = undefined
|
|
rolloutName = undefined
|
|
|
|
attrObjs = undefined
|
|
attrName = #()
|
|
attrMin = #()
|
|
attrMax = #()
|
|
|
|
expObj = undefined
|
|
expCont = undefined
|
|
expString = undefined
|
|
scalarObjects = #()
|
|
scalarNames = #()
|
|
scalarConts = #()
|
|
facialRollout = ""
|
|
|
|
newObjects = undefined
|
|
|
|
normalsXmlFile = undefined
|
|
masterScene = undefined
|
|
headScene = undefined
|
|
|
|
shaderType = undefined
|
|
-- normalsXmlFile = undefined
|
|
wrinkleFolder = undefined
|
|
|
|
debugPrintVal = true --toggle this true/false to enable/disable --print statements
|
|
chkPsdheadVal = false
|
|
useZeroControllers = true --toggle this to allow use of frozen transform controllers
|
|
|
|
returnData = #(#(),#(), #()) --[1] == new expString [2] == countFrom -USED DURING SCALE EXPRESSION ADJUSTMENT
|
|
initCountFrom = undefined --used to see if countfrom has incremented. If it hasnt then we can stop -USED DURING SCALE EXPRESSION ADJUSTMENT
|
|
|
|
|
|
facialBonePrefix = "FACIAL" --set here so we know what the prefix on facial bones is for selecting via name
|
|
|
|
global generateScaleOffsetNode = false --used to track if we need to add a scale offset joystick into the scale expressions
|
|
|
|
toolsRoot = RsConfigGetToolsRootDir()
|
|
theWildWest = RsConfigGetWildWestDir()
|
|
|
|
boneTagMappingXmlFile = (toolsRoot + "/etc/content/animconfig/bone_tags.xml")
|
|
|
|
filein (theWildWest + "script/3dsMax/_common_functions/FN_RSTA_Rigging.ms" )
|
|
|
|
frameCTRLNodes = #(
|
|
"nose_L_CTRL",
|
|
"innerBrow_L_CTRL",
|
|
"outerBrow_L_CTRL",
|
|
"eye_R_CTRL",
|
|
"eye_L_CTRL",
|
|
"innerBrow_R_CTRL",
|
|
"mouth_CTRL",
|
|
"tongue_CTRL",
|
|
"jaw_CTRL",
|
|
"nose_R_CTRL",
|
|
"outerBrow_R_CTRL"
|
|
)
|
|
|
|
dupJoints = #(
|
|
"SKEL_Spine3",
|
|
"SKEL_Neck_1",
|
|
"SKEL_Head"
|
|
)
|
|
|
|
|
|
oldNames = #(
|
|
"SKEL_Head",
|
|
"RB_Neck_1",
|
|
"SKEL_Neck_1"
|
|
)
|
|
|
|
GTANames = #(
|
|
#(
|
|
"SKEL_Head_OLD",
|
|
"RB_Neck_1_OLD",
|
|
"SKEL_Neck_1_OLD"
|
|
),
|
|
#(
|
|
"SKEL_Head",
|
|
"RB_Neck_1",
|
|
"SKEL_Neck_1",
|
|
"SKel_Neck_1"
|
|
)
|
|
)
|
|
|
|
geoNames = #( --names from fbx file
|
|
#(
|
|
-- "AsymmetricMesh",
|
|
-- "Teef_000_u"
|
|
),
|
|
#( --names for gta
|
|
-- "head_000_r",
|
|
-- "Teef_000_u"
|
|
"head_000_",
|
|
"Teef_000_"
|
|
)
|
|
)
|
|
|
|
faceCTRLS = #( --on face controls that need the facial scale flags set
|
|
-- "lowerLip_L_CTRL",
|
|
-- "lowerLip_C_CTRL",
|
|
-- "lowerLip_R_CTRL",
|
|
-- "lipCorner_R_CTRL",
|
|
-- "upperLip_C_CTRL",
|
|
-- "upperLip_L_CTRL",
|
|
-- "lipCorner_L_CTRL",
|
|
-- "upperLip_R_CTRL",
|
|
-- "eyelidUpperOuter_L_CTRL",
|
|
-- "eyelidUpperInner_L_CTRL",
|
|
-- "eyelidLowerOuter_L_CTRL",
|
|
-- "eyelidLowerInner_L_CTRL",
|
|
-- "eyelidLowerOuter_R_CTRL",
|
|
-- "eyelidLowerInner_R_CTRL",
|
|
-- "eyelidUpperOuter_R_CTRL",
|
|
-- "eyelidUpperInner_R_CTRL"
|
|
"eyelidUpperInner_R_CTRL",
|
|
"eyelidLowerInner_R_CTRL",
|
|
"lowerLip_L_CTRL",
|
|
"eyelidLowerOuter_R_CTRL",
|
|
"lowerLip_C_CTRL",
|
|
"eyelidLowerInner_L_CTRL",
|
|
"lowerLip_R_CTRL",
|
|
"eyelidLowerOuter_L_CTRL",
|
|
"lipCorner_R_CTRL",
|
|
"eyelidUpperInner_L_CTRL",
|
|
"upperLip_C_CTRL",
|
|
"eyelidUpperOuter_L_CTRL",
|
|
"upperLip_L_CTRL",
|
|
"eyelidUpperOuter_R_CTRL",
|
|
"lipCorner_L_CTRL",
|
|
"upperLip_R_CTRL",
|
|
"upperLip_R_OFF",
|
|
"lipCorner_L_OFF",
|
|
"eyelidUpperOuter_L_OFF",
|
|
"upperLip_L_OFF",
|
|
"eyelidUpperInner_L_OFF",
|
|
"upperLip_C_OFF",
|
|
"eyelidLower_L_OFF",
|
|
"eyelidLowerOuter_L_OFF",
|
|
"lipCorner_R_OFF",
|
|
"eyelidLowerInner_L_OFF",
|
|
"lowerLip_R_OFF",
|
|
"eyelidLower_R_OFF",
|
|
"eyelidLowerOuter_R_OFF",
|
|
"lowerLip_C_OFF",
|
|
"eyelidLowerInner_R_OFF",
|
|
"lowerLip_L_OFF",
|
|
"eyelidUpper_R_OFF",
|
|
"eyelidUpperOuter_R_OFF",
|
|
"eyelidUpper_L_OFF",
|
|
"eyelidUpperInner_R_OFF",
|
|
"jaw_C_OFF"
|
|
)
|
|
|
|
rigBones = #() --dynamically populated array of bones which have had expressions on them
|
|
facialGUIFile = undefined
|
|
facialFbxFile = undefined
|
|
facialXmlFile = undefined
|
|
|
|
controlGUIObjects = #() -- array used to store all gui objects for later scale concatenation
|
|
|
|
autoClick = undefined --this is a simple tag for the fbx importer for if we can auto click everything or if the usr needs to manually click ok after updating a setting.
|
|
|
|
foundPLayerShader = undefined --used to store if scene has PLAYER materials or old school multisubs
|
|
|
|
rsGUIFile = (theProjectRoot + "art/peds/3LateralSetup/RockStar_GTAV_GUI.max") --aplhad GUI file
|
|
rsOffsetJSFile = (theProjectRoot + "art/peds/3LateralSetup/ScaleOffsetJS.max") --scale joystick
|
|
|
|
|
|
standardGui = #( --list of all geo based gui nodes which will get replaced by the alphad plane ones
|
|
"faceControls_FRAME",
|
|
"mouth_FRAME",
|
|
"mouth_CTRL",
|
|
"mouth_TEXT",
|
|
"jaw_FRAME",
|
|
"jaw_CTRL",
|
|
"jaw_TEXT",
|
|
"tongue_TEXT",
|
|
"tongueMove_FRAME",
|
|
"tongueMove_CTRL",
|
|
"tongueRoll_FRAME",
|
|
"tongueRoll_CTRL",
|
|
"tongueInOut_FRAME",
|
|
"tongueInOut_CTRL",
|
|
"outerBrow_R_FRAME",
|
|
"outerBrow_R_CTRL",
|
|
"innerBrow_L_FRAME",
|
|
"innerBrow_L_CTRL",
|
|
"outerBrow_L_FRAME",
|
|
"outerBrow_L_CTRL",
|
|
"brows_TEXT",
|
|
"innerBrow_R_FRAME",
|
|
"innerBrow_R_CTRL",
|
|
"eye_R_FRAME",
|
|
"eye_L_FRAME",
|
|
"eyes_TEXT",
|
|
"eye_C_FRAME",
|
|
"eye_C_CTRL",
|
|
"eye_L_CTRL",
|
|
"eye_R_CTRL",
|
|
"nose_L_FRAME",
|
|
"nose_L_CTRL",
|
|
"nose_R_FRAME",
|
|
"nose_R_CTRL",
|
|
"nose_TEXT",
|
|
"cheek_TEXT",
|
|
"cheek_L_FRAME",
|
|
"cheek_L_CTRL",
|
|
"cheek_R_FRAME",
|
|
"cheek_R_CTRL",
|
|
"lowerLip_L_CTRL",
|
|
"lowerLip_C_CTRL",
|
|
"lowerLip_R_CTRL",
|
|
"lipCorner_R_CTRL",
|
|
"upperLip_C_CTRL",
|
|
"upperLip_L_CTRL",
|
|
"lipCorner_L_CTRL",
|
|
"upperLip_R_CTRL",
|
|
"eyelidUpperOuter_L_CTRL",
|
|
"eyelidUpperInner_L_CTRL",
|
|
"eyelidLowerOuter_L_CTRL",
|
|
"eyelidLowerInner_L_CTRL",
|
|
"eyelidLowerOuter_R_CTRL",
|
|
"eyelidLowerInner_R_CTRL",
|
|
"eyelidUpperOuter_R_CTRL",
|
|
"eyelidUpperInner_R_CTRL"
|
|
)
|
|
|
|
attrObjs = #( --objects with attrs used to connect to alpha attr gui. If id 2 = undefined this gets the attr from the definition if not undefined its cos this attr name is shared on multiple objects.
|
|
#("eye_C_CTRL", undefined),
|
|
#("mouth_CTRL", undefined),
|
|
#("tongueInOut_CTRL", undefined),
|
|
#("tongueRoll_CTRL", undefined),
|
|
#("jaw_CTRL", undefined),
|
|
#("lipCorner_R_CTRL", "CIRC_stickyLips_A"),
|
|
#("upperLip_R_CTRL", "CIRC_thinThick_B" ),
|
|
#("upperLip_C_CTRL", "CIRC_thinThick_C"),
|
|
#("upperLip_L_CTRL", "CIRC_thinThick_D"),
|
|
#("lipCorner_L_CTRL", "CIRC_stickyLips_E"),
|
|
#("lowerLip_L_CTRL", "CIRC_thinThick_F"),
|
|
#("lowerLip_C_CTRL", "CIRC_thinThick_G"),
|
|
#("lowerLip_R_CTRL", "CIRC_thinThick_H")
|
|
)
|
|
|
|
nonConcatJoints = #( --joints which we do not want to concat scale
|
|
"FACIAL_R_lipUpperAnalog",
|
|
"FACIAL_R_lipLowerAnalog",
|
|
"FACIAL_lipUpperAnalog",
|
|
"FACIAL_L_lipLowerAnalog",
|
|
"FACIAL_L_lipCornerAnalog",
|
|
"FACIAL_L_lipUpperAnalog",
|
|
"FACIAL_R_lipCornerAnalog",
|
|
"FACIAL_lipLowerAnalog",
|
|
|
|
"FACIAL_R_eyelidUpperInnerAnalog",
|
|
"FACIAL_R_eyelidLowerInnerAnalog",
|
|
"FACIAL_R_eyelidUpperOuterAnalog",
|
|
--"FACIAL_R_eyelidLowerLowerAnalog",
|
|
"FACIAL_R_eyelidLowerOuterAnalog",
|
|
|
|
"FACIAL_L_eyelidUpperInnerAnalog",
|
|
"FACIAL_L_eyelidLowerInnerAnalog",
|
|
"FACIAL_L_eyelidUpperOuterAnalog",
|
|
--"FACIAL_L_eyelidLowerLowerAnalog",
|
|
"FACIAL_L_eyelidLowerOuterAnalog"
|
|
|
|
|
|
|
|
)
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
fn getToolRevision toolFileName =
|
|
(
|
|
--toolFileName = (RsConfigGetWildWestDir() + "script\\3dsMax\\Characters\\Rigging\\ambientFacial\\faceRigger_arcGuiCreation.ms")
|
|
|
|
if runFromRigToolsPallette == true do
|
|
(
|
|
if rigToolsFileName != undeifned do
|
|
(
|
|
toolFileName = rigToolsFileName
|
|
)
|
|
)
|
|
fileLength = toolFileName.count
|
|
subst = (substring toolFileName (fileLength - 2) -1)
|
|
|
|
if subst == ".ms" then
|
|
(
|
|
testSync = true
|
|
)
|
|
else
|
|
(
|
|
testSync = false
|
|
)
|
|
|
|
versionNumber = undefined
|
|
if testSync == true then
|
|
(
|
|
local fstats = ( gRsPerforce.getFileStats toolFileName )[ 1 ]
|
|
local haveRev = fstats.Item[ "haveRev" ] as integer
|
|
local headRev = fstats.Item[ "headRev" ] as integer
|
|
|
|
versionNumber = haveRev
|
|
)
|
|
else
|
|
(
|
|
messagebox ("WARNING! Could not version rig as could not deduct which version of this tool you are running from p4") beep:true title:"Versioning"
|
|
)
|
|
--messagebox ("version # :"+(versionNumber as string))
|
|
print ("version # :"+(versionNumber as string))
|
|
return versionNumber
|
|
)
|
|
|
|
fn swapChars textString charFrom charTo =
|
|
(
|
|
flt = filterString textString charFrom
|
|
|
|
thisNewString = ""
|
|
for i = 1 to flt.count do
|
|
(
|
|
endStr = ""
|
|
|
|
if i < flt.count do
|
|
(
|
|
endStr = charTo
|
|
)
|
|
thisNewString = thisNewString+flt[i]+endStr
|
|
)
|
|
|
|
return thisNewString
|
|
)
|
|
|
|
fn copyTexture initialPath finalPath =
|
|
(
|
|
|
|
initStr = initialPath
|
|
newFile = finalPath
|
|
|
|
-- initStr = "X://gta5//art//peds//Story_Characters//CS_TracyDiSanto//From_3L//2012-04-17_RockStar_GTAV_TracyDiSanto_v05//textures//HEAD_Wrinkle_Mask_0.tga"
|
|
|
|
|
|
|
|
thisFile = initStr
|
|
|
|
--clearListener()
|
|
|
|
flt = filterString thisFile "//"
|
|
|
|
origThisFile = thisFile
|
|
|
|
thisFile = swapChars thisFile "//" "\\"
|
|
|
|
flt = filterString newFile "//"
|
|
|
|
thisNewFile = swapChars newFile "//" "\\"
|
|
|
|
origNewFile = newFile
|
|
|
|
|
|
ex = doesFileExist thisFile
|
|
|
|
if ex == true then
|
|
(
|
|
-- format ("\n"+"************** FILE EXISTS **********************"+"\n")
|
|
|
|
--newPath = swapChars thisNewFile "//" "\\"
|
|
--file exists so we should delete the original
|
|
free thisFile
|
|
deleteFile thisFile
|
|
ex2 = doesFileExist thisFile
|
|
if ex2 == true then
|
|
(
|
|
format ("\t"+"file deletion FAILED."+"\n")
|
|
format ("\t"+(thisFile as string)+"\n")
|
|
)
|
|
else
|
|
(
|
|
-- format ("\t"+"file deletion SUCCESS!"+"\n")
|
|
)
|
|
|
|
-- newFile = "c:\\textureCopy\\Head_Wrinkle_Mask_0.tga"
|
|
|
|
format ("\n\n"+"copying From: "+"\n\t"+origthisFile+"\n"+"To: "+"\n\t"+origNewFile+"\n\n\n")
|
|
|
|
--newFile = copyFile thisFile thisNewFile
|
|
newFile = copyFile origThisFile origNewFile
|
|
|
|
-- format ("\n\n"+"File copy status: "+(newFile as string)+"\n")
|
|
|
|
ex2 = doesFileExist origNewFile
|
|
|
|
if ex2 == true then
|
|
(
|
|
--print ("Copied to "+thisNewFile)
|
|
)
|
|
else
|
|
(
|
|
print "Copy failed. :("
|
|
)
|
|
)
|
|
else
|
|
(
|
|
print ("Couldn't find "+thisFile)
|
|
)
|
|
|
|
return thisNewFile
|
|
)
|
|
|
|
fn moveWrinkleMap wrinklePath mapNames = --copies wrinkles from original source 3lateral folder to characters textures\highres folder
|
|
(
|
|
--first we need to find the real texture folder
|
|
thisStr = findString wrinklePath "From" --searching for 'From' as textures are always inside a From_3l or From3L folder
|
|
|
|
realFolder = undefined
|
|
|
|
if thisStr != undefined then
|
|
(
|
|
realFolder = substring wrinklePath 1 (thisStr - 1)
|
|
|
|
---messagebox ("Found "+realFolder)
|
|
)
|
|
else
|
|
(
|
|
if queryBox ("Warning! Could not define character texture folder."+"\n"+"Please Click Yes to select character\\textures\\highres folder"+"\n"+"or No to cancel script.") beep:true then
|
|
(
|
|
realFolder = getOpenFileName caption:"Textures Folder" types:"Tga files (head*diff*.tga)|head_*diff*.tga|All Files (*.*)|*.*|"
|
|
)
|
|
else
|
|
(
|
|
contin = false
|
|
)
|
|
)
|
|
|
|
if realFolder != undefined then --now we do the real stuff
|
|
(
|
|
for wm = 1 to mapNames[2].count do
|
|
(
|
|
--first off check if the map already exists in the realFolder
|
|
|
|
fileName = filenameFromPath mapNames[1][wm]
|
|
|
|
mPath = (realFolder+"textures\\highres\\"+fileName)
|
|
|
|
bPath = swapChars mPath "\\" "//"
|
|
|
|
mPath = bPath
|
|
|
|
--messagebox ("Looking for: "+(mPath) as string)
|
|
--print ("Looking for existing: "+(mPath) as string)
|
|
|
|
fileExists = doesFileExist (mPath) --dont think i need this with the 4 funcitonality
|
|
|
|
format ("fileExists for "+(mPath)+" = "+(fileExists as string)+"\n")
|
|
--if it does then check out of p4 then copy the new one over the top
|
|
if fileExists == true then
|
|
(
|
|
print "Existing wrinkle Found!"
|
|
--messagebox "Copying over existing wrinkle"
|
|
thisFile = (mPath)
|
|
|
|
thisFile = swapChars thisFile "//" "\\"
|
|
|
|
--thisFile = copyFile mapNames[1][wm] (thisFile)
|
|
|
|
newTexture = copyTexture mapNames[1][wm] mPath
|
|
|
|
format ("Replacement texture: "+(newTexture as string)+"\n")
|
|
|
|
newTexture1 = getFiles newTexture
|
|
|
|
if newTexture1.count == 1 do
|
|
(
|
|
newTexture1 = newTexture1[1]
|
|
|
|
-- gRsPerforce.add_or_edit #( mPath ) silent:true queueAdd:false
|
|
gRsPerforce.add_or_edit #( newTexture1 ) silent:true queueAdd:false
|
|
|
|
--messagebox "Found existing wrinkle"
|
|
|
|
--now replace mapNames[1][wm] with the new path
|
|
print ("Replacing entry "+(wm as string)+" with "+newTexture1)
|
|
-- mapNames[1][wm] = mPath
|
|
|
|
-- newTexture = execute newTexture
|
|
mapNames[1][wm] = newTexture1
|
|
)
|
|
)
|
|
--else copy the new one to realfolder and add to p4
|
|
else
|
|
(
|
|
--messagebox ("adding new wrinkle to "+mpath)
|
|
--print ("adding new wrinkle to "+mpath)
|
|
|
|
thisFile = mPath
|
|
|
|
-- flt = filterString thisFile "//"
|
|
|
|
-- thisFile = ""
|
|
-- for i = 1 to flt.count do
|
|
-- (
|
|
-- thisFile = thisFile+flt[i]+"\\"
|
|
-- )
|
|
|
|
thisFile = swapChars thisFile "//" "\\"
|
|
|
|
--thisFile = copyFile mapNames[1][wm] (thisFile)
|
|
|
|
newTexture = copytexture mapNames[1][wm] mPath
|
|
|
|
if newTexture == false do
|
|
(
|
|
format ("Copy of "+mPath +" FAILED!")
|
|
)
|
|
|
|
format ("New texture: "+(newTexture as string)+"\n")
|
|
|
|
newTexture1 = getFiles newTexture
|
|
|
|
if newTexture1.count == 1 then
|
|
(
|
|
newTexture1 = newTexture1[1]
|
|
-- gRsPerforce.add_or_edit #( mPath ) silent:true queueAdd:false
|
|
gRsPerforce.add_or_edit #( newTexture1 ) silent:true queueAdd:false
|
|
|
|
--now replace mapNames[1][wm] with the new path
|
|
print ("Replacing entry "+(wm as string)+" with "+newTexture1)
|
|
-- mapNames[1][wm] = mPath
|
|
|
|
-- newTexture = execute newTexture
|
|
mapNames[1][wm] = newTexture1
|
|
)
|
|
else
|
|
(
|
|
format ("WARNING!: "+(newTexture1.count as string))
|
|
)
|
|
)
|
|
)
|
|
)
|
|
else
|
|
(
|
|
--messagebox ("realFolder == undefined")
|
|
-- break()
|
|
contin = false
|
|
)
|
|
)
|
|
fn deactivateHeels =
|
|
(
|
|
heelJs = getNodeByName "HeelHeight"
|
|
|
|
if heelJs != undefined do
|
|
(
|
|
in coordsys parent heelJs.position.controller[2].Y_Position = 1.0
|
|
)
|
|
)
|
|
|
|
fn connectAlphaGUIToAttrs =
|
|
(
|
|
--print "------------------"
|
|
|
|
for i = 1 to attrObjs.count do
|
|
(
|
|
obj = getNodeByName attrObjs[i][1]
|
|
|
|
if attrObjs[i][2] == undefined then
|
|
(
|
|
|
|
|
|
attrDef = custAttributes.get obj.modifiers[#Attribute_Holder] 1
|
|
|
|
attrNames = getPropNames attrDef
|
|
|
|
for a = 1 to attrNames.count do
|
|
(
|
|
--print ("Current attr = "+(attrNames[a] as string))
|
|
attName = (attrNames[a] as string)
|
|
attLength = attName.count
|
|
attributeName = (substring attName 1 (attLength - 3))
|
|
guiObj = getNodeByName ("CIRC_"+attributeName)
|
|
|
|
if guiObj != undefined then
|
|
(
|
|
--now we need to wire this attr to the gui object
|
|
|
|
--so now we build the path to the Attribute
|
|
|
|
attrStr = ("$"+obj.name+".modifiers[#Attribute_Holder]."+attrNames[a])
|
|
|
|
thisAttr = execute attrStr
|
|
|
|
if thisAttr != undefined then
|
|
(
|
|
fromStr = ("$"+obj.name+".modifiers[#Attribute_Holder]."+obj.name+"_A"+"[#"+attributeName+"_CA] ")
|
|
toStr = ("$CIRC_"+attributeName+".pos.controller.Zero_Pos_XYZ.controller.X_Position.controller[#Limited_Controller__Bezier_Float] "+"\""+"Limited_Controller__Bezier_Float"+"\""+" "+"\""+attributeName+"_CA"+"\"")
|
|
|
|
wireStr = ("paramWire.connect2way "+fromStr + toStr)
|
|
--print (wireStr)
|
|
execute wireStr
|
|
)
|
|
else
|
|
(
|
|
--print ("Attribute path generation failed for "+(attrObjs[i][1]+".modifiers[#Attribute_Holder]."+attrNames[a]))
|
|
)
|
|
)
|
|
else
|
|
(
|
|
--print ("Couldnt find "+("CIRC_"+attributeName))
|
|
)
|
|
)
|
|
)
|
|
else
|
|
(
|
|
guiObj = getNodeByName attrObjs[i][2]
|
|
guiObjNameLength = attrObjs[i][2].count
|
|
startChar = 6
|
|
trimmedLength = (guiObjNameLength - (1 + startChar))
|
|
attributeName = (substring guiObj.name startChar trimmedLength)
|
|
|
|
fromStr = ("$"+obj.name+".modifiers[#Attribute_Holder]."+obj.name+"_A"+"[#"+attributeName+"_CA] ")
|
|
toStr = ("$"+guiObj.name+".pos.controller.Zero_Pos_XYZ.controller.X_Position.controller[#Limited_Controller__Bezier_Float] "+"\""+"Limited_Controller__Bezier_Float"+"\""+" "+"\""+attributeName+"_CA"+"\"")
|
|
wireStr = ("paramWire.connect2way "+fromStr+toStr)
|
|
|
|
--print (wireStr)
|
|
execute wireStr
|
|
)
|
|
)
|
|
|
|
|
|
--print "Attrs connected"
|
|
)
|
|
|
|
|
|
fn convertStandardGuiToAlphaGUI =
|
|
(
|
|
mergeMaxFile rsGUIFile quiet:true
|
|
|
|
-- disableSceneRedraw()
|
|
max modify mode
|
|
|
|
for sG = 1 to standardGui.count do
|
|
(
|
|
stdGUI = getNodeByName standardGui[sG]
|
|
alpGUI = getNodeByName ("RS_"+standardGui[sG])
|
|
|
|
if alpGUI != undefined then
|
|
(
|
|
--do i need to parent the alpGUI to the stdGui.parent 1st?
|
|
alpGui.parent = stdGui.parent
|
|
|
|
in coordsys world alpGui.transform = in coordsys world stdGui.transform
|
|
|
|
select stdGui
|
|
|
|
--need to ensure we maintain existing attr holders
|
|
|
|
if stdGui.modifiers.count > 0 then
|
|
(
|
|
modCount = stdGUI.modifiers.count
|
|
val = (modCount - 1)
|
|
if val < 2 then
|
|
(
|
|
modPanel.setCurrentObject stdGui.baseObject
|
|
modPanel.addModToSelection (Edit_Poly ()) ui:on
|
|
maxOps.CollapseNodeTo stdGui 2 off
|
|
)
|
|
else
|
|
(
|
|
modPanel.setCurrentObject stdGui.modifiers[val]
|
|
modPanel.addModToSelection (Edit_Poly ()) ui:on
|
|
maxOps.CollapseNodeTo stdGui (modCount - 1) off
|
|
)
|
|
|
|
modPanel.setCurrentObject stdGui.baseObject
|
|
)
|
|
else
|
|
(
|
|
convertTo stdGui PolyMeshObject
|
|
)
|
|
subobjectLevel = 4
|
|
max select all
|
|
|
|
max delete
|
|
--now we can attach the alpha plane
|
|
stdGui.EditablePoly.attach alpGUI stDGUI
|
|
subobjectLevel = 0
|
|
)
|
|
else
|
|
(
|
|
--print ("Couldn't find RS node RS_"+standardGui[sG])
|
|
)
|
|
)
|
|
connectAlphaGUIToAttrs()
|
|
)
|
|
|
|
fn getNodeByNameWildcard nameString =
|
|
(
|
|
thisNode = undefined
|
|
for o in objects do
|
|
(
|
|
nameLength = nameString.count
|
|
|
|
thisName = nameString as Name
|
|
|
|
ObjectName = ((substring (o.name) 1 nameLength) as Name)
|
|
|
|
if objectName == thisName do
|
|
(
|
|
thisNode = o
|
|
debugprint ("WOOT "+o.name+" == "+thisName)
|
|
)
|
|
)
|
|
|
|
return thisNode
|
|
)
|
|
|
|
fn tagOnFaceCtrls =
|
|
(
|
|
tagDataArray = RSTA_populateBoneTagMappingArray boneTagMappingXmlFile
|
|
|
|
for i = 1 to faceCTRLS.count do
|
|
(
|
|
thisObj = getNodeByName faceCTRLS[i]
|
|
if thisObj != undefined do
|
|
(
|
|
scaleTag = ("True")
|
|
scaleTrackTag = "TRACK_FACIAL_SCALE"
|
|
existingTag = getUserPropBuffer thisObj
|
|
foundScale = findString existingTag "exportScale"
|
|
if foundScale != undefined do
|
|
(
|
|
scaleTag = "true"
|
|
)
|
|
foundScaleTrack = findString existingTag "scaleTrackType"
|
|
|
|
if foundScaleTrack != undefined do
|
|
(
|
|
scaleTrackTag = "TRACK_FACIAL_TRANSLATION"
|
|
)
|
|
|
|
bTag = RSTA_findBoneTag thisObj.name tagDataArray
|
|
|
|
if bTag != "UNKNOWN" do
|
|
(
|
|
setUserProp thisObj "tag" bTag
|
|
)
|
|
setUserProp thisObj "exportTrans" "True"
|
|
setUserProp thisObj "exportScale" scaleTag
|
|
setuserProp thisObj "scaleTrackType" scaleTrackTag
|
|
)
|
|
)
|
|
|
|
filein (RsConfigGetWildWestDir() + "script/3dsMax/Characters/Rigging/3Lateral/ThreeLateral_tagCustAttrGui.ms")
|
|
)
|
|
|
|
fn prepForTest =
|
|
(
|
|
oldFaceControls = #($innerBrow_R_FRAME, $faceControls_FRAME, $cheek_R_FRAME, $mouth_FRAME, $mouth_CTRL, $mouth_TEXT, $cheek_L_CTRL, $jaw_FRAME, $jaw_CTRL, $jaw_TEXT, $cheek_L_FRAME, $tongue_TEXT, $cheek_TEXT, $tongueMove_FRAME, $tongueMove_CTRL, $nose_TEXT, $tongueRoll_FRAME, $tongueRoll_CTRL, $nose_R_CTRL, $tongueInOut_FRAME, $tongueInOut_CTRL, $nose_R_FRAME, $nose_L_CTRL, $outerBrow_R_FRAME, $outerBrow_R_CTRL, $nose_L_FRAME, $innerBrow_L_FRAME, $innerBrow_L_CTRL, $eye_C_CTRL, $outerBrow_L_FRAME, $outerBrow_L_CTRL, $brows_TEXT, $eye_C_FRAME, $cheek_R_CTRL, $innerBrow_R_CTRL, $eyes_TEXT, $eye_L_CTRL, $eye_R_FRAME, $eye_L_FRAME, $eye_R_CTRL, $eye_R_DRIVER, $eye_L_OFF, $eye_R_SDK, $eye_L_SDK, $eye_R_OFF, $eye_L_DRIVER, $eyes_OFF, $eye_C_OFF, $innerBrow_R_OFF, $outerBrow_L_OFF, $nose_OFF, $nose_L_OFF, $innerBrow_L_OFF, $outerBrow_R_OFF, $nose_R_OFF, $brows_OFF, $tongueInOut_OFF, $tongueRoll_OFF, $cheeks_OFF, $tongueMove_OFF, $cheek_L_OFF, $tongue_OFF, $jaw_OFF, $cheek_R_OFF, $mouth_OFF, $faceControls_OFF, $lipCorner_R_CTRL, $upperLip_L_CTRL, $upperLip_C_CTRL, $lowerLip_L_CTRL, $upperLip_R_CTRL, $lowerLip_C_CTRL, $lipCorner_L_CTRL, $lowerLip_R_CTRL, $lipCorner_R_OFF, $lowerLip_R_OFF, $upperLip_R_OFF, $lowerLip_C_OFF, $upperLip_C_OFF, $lowerLip_L_OFF, $upperLip_L_OFF, $jaw_C_OFF, $lipCorner_L_OFF, $head_C_OFF)
|
|
|
|
oldFaceJoints = #($FACIAL_facialRoot, $FACIAL_jaw, $FACIAL_underChin, $FACIAL_L_underChin, $FACIAL_chin, $FACIAL_chinSkinBottom, $FACIAL_L_chinSkinBottom, $FACIAL_R_chinSkinBottom, $FACIAL_tongueA, $FACIAL_tongueB, $FACIAL_tongueC, $FACIAL_chinSkinTop, $FACIAL_L_chinSkinTop, $FACIAL_chinSkinMid, $FACIAL_L_chinSkinMid, $FACIAL_L_chinSide, $FACIAL_L_lipLower, $FACIAL_L_lipLowerAnalog, $FACIAL_L_lipLowerThicknessV, $FACIAL_L_lipLowerThicknessH, $FACIAL_lipLower, $FACIAL_lipLowerAnalog, $FACIAL_lipLowerThicknessV, $FACIAL_lipLowerThicknessH, $FACIAL_R_chinSkinMid, $FACIAL_R_chinSkinTop, $FACIAL_R_chinSide, $FACIAL_R_lipLower, $FACIAL_R_lipLowerAnalog, $FACIAL_R_lipLowerThicknessV, $FACIAL_R_lipLowerThicknessH, $FACIAL_R_underChin, $FACIAL_nose, $FACIAL_L_nostril, $FACIAL_L_nostrilThickness, $FACIAL_noseLower, $FACIAL_L_noseLowerThickness, $FACIAL_R_noseLowerThickness, $FACIAL_noseTip, $FACIAL_R_nostril, $FACIAL_R_nostrilThickness, $FACIAL_noseUpper, $FACIAL_L_noseUpper, $FACIAL_noseBridge, $FACIAL_L_nasolabialFurrow, $FACIAL_L_nasolabialBulge, $FACIAL_L_cheekLower, $FACIAL_L_cheekLowerBulge1, $FACIAL_L_cheekLowerBulge2, $FACIAL_L_cheekInner, $FACIAL_L_cheekOuter, $FACIAL_L_eyesackLower, $FACIAL_L_eyeball, $FACIAL_L_eyelidLower, $FACIAL_L_eyelashLowerOuter, $FACIAL_L_eyelashLowerInner, $FACIAL_L_eyelidUpper, $FACIAL_L_eyelashUpperOuter, $FACIAL_L_eyelashUpperInner, $FACIAL_L_eyesackUpperOuterBulge, $FACIAL_L_eyesackUpperInnerBulge, $FACIAL_L_eyesackUpperOuterFurrow, $FACIAL_L_eyesackUpperInnerFurrow, $FACIAL_forehead, $FACIAL_L_foreheadInner, $FACIAL_L_foreheadInnerBulge, $FACIAL_L_foreheadOuter, $FACIAL_skull, $FACIAL_foreheadUpper, $FACIAL_L_foreheadUpperInner, $FACIAL_L_foreheadUpperOuter, $FACIAL_R_foreheadUpperInner, $FACIAL_R_foreheadUpperOuter, $FACIAL_L_temple, $FACIAL_L_ear, $FACIAL_L_earLower, $FACIAL_L_masseter, $FACIAL_L_jawRecess, $FACIAL_L_cheekOuterSkin, $FACIAL_L_lipUpper, $FACIAL_L_lipUpperAnalog, $FACIAL_L_lipUpperThicknessH, $FACIAL_L_lipUpperThicknessV, $FACIAL_lipUpper, $FACIAL_lipUpperAnalog, $FACIAL_lipUpperThicknessH, $FACIAL_lipUpperThicknessV, $FACIAL_L_lipCorner, $FACIAL_L_lipCornerAnalog, $FACIAL_L_lipCornerThicknessUpper, $FACIAL_L_lipCornerThicknessLower, $FACIAL_R_lipUpper, $FACIAL_R_lipUpperAnalog, $FACIAL_R_lipUpperThicknessH, $FACIAL_R_lipUpperThicknessV, $FACIAL_R_lipCorner, $FACIAL_R_lipCornerAnalog, $FACIAL_R_lipCornerThicknessUpper, $FACIAL_R_lipCornerThicknessLower, $FACIAL_R_cheekLower, $FACIAL_R_cheekLowerBulge1, $FACIAL_R_cheekLowerBulge2, $FACIAL_R_masseter, $FACIAL_R_jawRecess, $FACIAL_R_ear, $FACIAL_R_earLower, $FACIAL_R_eyesackLower, $FACIAL_R_nasolabialBulge, $FACIAL_R_cheekOuter, $FACIAL_R_cheekInner, $FACIAL_R_noseUpper, $FACIAL_R_foreheadInner, $FACIAL_R_foreheadInnerBulge, $FACIAL_R_foreheadOuter, $FACIAL_R_cheekOuterSkin, $FACIAL_R_eyeball, $FACIAL_R_eyelidUpper, $FACIAL_R_eyelashUpperOuter, $FACIAL_R_eyelashUpperInner, $FACIAL_R_eyelidLower, $FACIAL_R_eyelashLowerOuter, $FACIAL_R_eyelashLowerInner, $FACIAL_R_eyesackUpperInnerFurrow, $FACIAL_R_eyesackUpperOuterFurrow, $FACIAL_R_eyesackUpperInnerBulge, $FACIAL_R_eyesackUpperOuterBulge, $FACIAL_R_nasolabialFurrow, $FACIAL_R_temple, $FACIAL_adamsApple)
|
|
|
|
oldGeoNodes = #($Teef_000_u, $head_000_r)
|
|
|
|
delete oldFaceControls
|
|
debugPrint "Deleted oldFaceControls"
|
|
delete oldFaceJoints
|
|
debugPrint "Deleted oldFaceJoints"
|
|
delete oldGeoNodes
|
|
debugPrint "Deleted oldGeoNodes"
|
|
)
|
|
|
|
|
|
rollout progBar "XML Parse Progress..."
|
|
(
|
|
progressBar prog pos:[10,10] color:green
|
|
)
|
|
|
|
fn debugPrint printStr = --this is a little function to replace the --print command. This allows us then to be able to globally turn on and off --print cstatements.
|
|
(
|
|
if debugPrintVal == true do
|
|
(
|
|
print printStr
|
|
)
|
|
)
|
|
|
|
|
|
fn LSW_EnvelopeCallbackFunction =
|
|
(
|
|
WindowHandle = DialogMonitorOPS.GetWindowHandle()
|
|
theDialogName = UIAccessor.GetWindowText WindowHandle
|
|
|
|
if theDialogName != undefined and matchpattern theDialogName pattern:"*Load Envelopes*" do
|
|
UIAccessor.PressButtonByName WindowHandle "Match by Name"
|
|
|
|
if theDialogName != undefined and matchpattern theDialogName pattern:"*Load Envelopes*" do
|
|
UIAccessor.PressButtonByName WindowHandle "OK"
|
|
|
|
true
|
|
)
|
|
|
|
|
|
fn loadSkinData geo =
|
|
(
|
|
|
|
boneList = #()
|
|
skinFile = ("c:/skins/"+"3Lat_"+geo.name+".env")
|
|
boneFile = ("c:/skins/"+"3Lat_"+geo.name+".bon")
|
|
|
|
for o in objects do
|
|
(
|
|
if (substring o.name 1 4) == "SKEL" do
|
|
(
|
|
appendIfUnique boneList o
|
|
)
|
|
)
|
|
|
|
-- This part adds a skin modifier, sets the bone limit, adds the bones
|
|
if geo.modifiers[#Skin] == undefined do
|
|
(
|
|
select geo
|
|
|
|
modPanel.addModToSelection (XForm ()) ui:on
|
|
execStr = ("collapseStack $"+geo.name)
|
|
execute execStr
|
|
|
|
modPanel.addModToSelection (Skin ()) ui:on
|
|
|
|
geo.modifiers[#Skin].bone_Limit = vtxWeight
|
|
geo.modifiers[#Skin].showNoEnvelopes = on
|
|
)
|
|
|
|
|
|
if boneFile != undefined then
|
|
(
|
|
f = openfile boneFile
|
|
inputData = #() -- define as array
|
|
while not eof f do
|
|
(
|
|
append inputData (filterstring (readLine f) ",")
|
|
)
|
|
close f
|
|
|
|
for i in inputData do
|
|
(
|
|
currBonename = (i as string)
|
|
currBoneLength = currBonename.count
|
|
currBone = ("$"+(substring currBonename 4 (currBonelength - 5)))
|
|
|
|
executeStr = ("if "+currBone+" != undefined do ("+"select "+currBone+")")
|
|
currentBone = execute executeStr
|
|
currentBone = execute currBone
|
|
|
|
if currentBone != undefined then
|
|
(
|
|
appendIfUnique boneList $
|
|
)
|
|
else
|
|
(
|
|
debugprint ("Couldn't find "+currBone+" in this scene.")
|
|
)
|
|
)
|
|
|
|
select geo
|
|
SetCommandPanelTaskMode mode:#modify
|
|
|
|
for i = 1 to boneList.count do
|
|
(
|
|
boneToAdd = getNodeByName bonelist[i].name
|
|
|
|
updateInt = 1
|
|
if i != boneList.count do
|
|
(
|
|
updateInt = 0
|
|
)
|
|
|
|
if boneToAdd != undefined do
|
|
(
|
|
foundThisBone = false
|
|
--now we check if this bone name is already in the skin
|
|
numberBones = skinops.GetNumberBones geo.modifiers[#Skin]
|
|
for nB = 1 to numberBones do
|
|
(
|
|
ThisBoneName = skinops.getBoneName geo.modifiers[#Skin] nB 0
|
|
if ThisBoneName == boneList[i].name do
|
|
(
|
|
foundThisBone = true
|
|
)
|
|
)
|
|
|
|
--ok so we CAN add this bone in
|
|
if foundThisBone == false do
|
|
(
|
|
skinOps.addbone geo.modifiers[#Skin] boneList[i] updateInt
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
-- Load the skin weights back on.
|
|
-- Need to use completeRedraw() or the weights wont load when in a loop. Madness.
|
|
-- Fix was from here: http://tech-artists.org/forum/showthread.php?p=4034
|
|
-- Use a callback to press the buttons
|
|
-- I found this here: http://forums.cgsociety.org/showthread.php?t=485300
|
|
DialogMonitorOPS.RegisterNotification LSW_EnvelopeCallbackFunction ID:#ANoon_Envelopes
|
|
DialogMonitorOPS.Enabled = true
|
|
|
|
completeRedraw()
|
|
skinOps.loadEnvelope geo.modifiers[#Skin] skinFile
|
|
|
|
DialogMonitorOPS.Enabled = false
|
|
DialogMonitorOPS.UnRegisterNotification ID:#ANoon_Envelopes
|
|
)
|
|
|
|
|
|
fn saveSkinData geo =
|
|
(
|
|
debugprint ("*** SAVE SKINNING on "+(geo as string)+" ***")
|
|
boneList = #()
|
|
|
|
makeDir "c:/skins"
|
|
|
|
select geo
|
|
max modify mode
|
|
subobjectLevel = 1
|
|
modPanel.setCurrentObject geo.modifiers[#Skin]
|
|
|
|
--save out the skin weights
|
|
skinFile = ("c:/skins/"+"3Lat_"+geo.name+".env")
|
|
|
|
skinOps.saveEnvelope geo.modifiers[#Skin] skinFile
|
|
|
|
boneFile = ("c:/skins/"+"3Lat_"+geo.name+".bon")
|
|
|
|
skinMod = geo.modifiers[#Skin]
|
|
totalSkinModBones = skinOps.getNumberBones skinMod
|
|
|
|
if totalSkinModBones > 0 then
|
|
(
|
|
|
|
output_name = boneFile
|
|
|
|
if output_name != undefined then
|
|
(
|
|
output_file = createfile output_name
|
|
|
|
for i = 1 to totalSkinModBones do
|
|
(
|
|
thebonename = skinOps.getBoneName skinMod i 1
|
|
append boneList theBoneName
|
|
format ((theBoneName as string)+"\n") to:output_file
|
|
)
|
|
close output_file
|
|
)--end if
|
|
)--end if
|
|
)
|
|
|
|
|
|
fn scaleFixUpScaleByScale expString = --adds in a -1 to all input values in scale driven by scale expressions due to game scale default being 0 but max being 1
|
|
(
|
|
strA = "> 3., 3.,"
|
|
strARep = "> (3.0 - 1), (3.0 - 1),"
|
|
|
|
strB = "< 0.333333, 0.333333,"
|
|
strBRep = "< (0.333333 - 1), (0.333333 - 1),"
|
|
|
|
strC = "< 1.,"
|
|
strCRep = "< (1.0 - 1),"
|
|
|
|
--first off we'll double check this hasnt already been done
|
|
exist = findString expString strARep
|
|
if exist == undefined do
|
|
(
|
|
startPoint = findString expString strA
|
|
expString = replace expString startPoint (strA.count) strARep
|
|
)
|
|
|
|
exist = findString expString strBRep
|
|
if exist == undefined do
|
|
(
|
|
startPoint = findString expString strB
|
|
expString = replace expString startPoint (strB.count) strBRep
|
|
)
|
|
|
|
exist = findString expString strCRep
|
|
if exist == undefined do
|
|
(
|
|
startPoint = findString expString strC
|
|
expString = replace expString startPoint (strC.count) strCRep
|
|
)
|
|
|
|
return expString
|
|
)
|
|
|
|
-- function to generate an expression
|
|
fn generateExpressionIM expObj expCont scalarObjects scalarNames scalarConts expString=
|
|
(
|
|
--TEMPHACK
|
|
findSoff = "ScaleOffset"
|
|
|
|
-- print ("ExpString: "+(expString as string))
|
|
|
|
findSO = findString expString findSoff
|
|
if findSO != undefined do
|
|
(
|
|
findSoff2 = "ScaleOffset + 1"
|
|
|
|
findSo2 = findString expString findSoff2
|
|
|
|
if findSo2 != undefined then
|
|
(
|
|
--expString = substring expString findSO2 findSoff2.count
|
|
|
|
expString = ("( 0"+(substring expString (findSoff2.count + 2) -1))
|
|
|
|
print "Removing ScaleOffset + 1"
|
|
|
|
print ("ExpString reset to : "+(expString as string))
|
|
)
|
|
else
|
|
(
|
|
expString = substring expString findSo findSoff.count
|
|
|
|
print "Removing ScaleOffset"
|
|
|
|
print ("ExpString reset to : "+(expString as string))
|
|
)
|
|
|
|
)
|
|
|
|
if generateScaleOffsetNode == false then
|
|
(
|
|
expString = ("("+expString+")")
|
|
|
|
debugPrint "----------------------------------------------------------------------------"
|
|
debugPrint "\r\n"
|
|
debugPrint ("Creating expression on "+expObj+". Scalar of "+(scalarObjects as string))
|
|
debugPrint ("Using expression:")
|
|
debugPrint expString
|
|
debugPrint "\r\n"
|
|
debugPrint "----------------------------------------------------------------------------"
|
|
|
|
fcStr = ( "$"+expObj+expCont) --rebuild the string so it can be used below
|
|
local newfcStr = execute fcStr
|
|
debugPrint ("newfcStr = "+(fcStr as string))
|
|
|
|
--HACK TO TRY AND RESOLVE ON FACE CTRL ISSUE WITH PSD HEADS
|
|
|
|
if chkPsdheadVal == true do
|
|
(
|
|
expContStr = filterString expCont "."
|
|
|
|
newExpCont = expContStr[1]
|
|
|
|
contAxis = undefined
|
|
|
|
while contAxis == undefined do
|
|
(
|
|
for ax = 1 to expContStr.count do
|
|
(
|
|
if (substring expContStr[ax] 1 2) == "X_" then
|
|
(
|
|
contAxis = expContStr[ax]
|
|
)
|
|
else
|
|
(
|
|
if (substring expContStr[ax] 1 2) == "Y_" then
|
|
(
|
|
contAxis = expContStr[ax]
|
|
)
|
|
else
|
|
(
|
|
if (substring expContStr[ax] 1 2) == "Z_" then
|
|
(
|
|
contAxis = expContStr[ax]
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
if ax == expContStr then
|
|
(
|
|
if contAxis == undefined do
|
|
(
|
|
--hmm ok we oculdnt find a X Y or Z controller
|
|
format ("hmm ok we oculdnt find a X Y or Z controller\n")
|
|
break()
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
ct = undefined
|
|
if newExpCont == "Position" then
|
|
(
|
|
ct = "Position_XYZ"
|
|
)
|
|
else
|
|
(
|
|
if newExpCont == "Rotation" then
|
|
(
|
|
ct = "Euler_XYZ"
|
|
)
|
|
else
|
|
(
|
|
ct = "ScaleXYZ"
|
|
)
|
|
)
|
|
|
|
fcStr = ( "$"+expObj+"."+newExpCont+".available.controller = "+ct+" ()")
|
|
|
|
--format ("1: fcStr: "+fcStr+"\n")
|
|
newFcStr = execute fcStr
|
|
--format "1 went thru\n"
|
|
cCountStr = ("$"+expObj+"."+newExpCont+".controller.count")
|
|
cCount = execute cCountStr
|
|
|
|
fcStr = ("$"+expObj+"."+newExpCont+".controller["+((cCount - 1) as string)+"]."+contAxis+".controller = Float_Expression ()")
|
|
--format ("2: fcStr: "+fcStr+"\n")
|
|
newFcStr = execute fcStr
|
|
--format "2 went thru\n"
|
|
|
|
--END PSD HACK
|
|
)
|
|
|
|
if scalarNames.count != 0 do
|
|
(
|
|
for i = 1 to scalarNames.count do --this should loop through the array of scalars and their controllers and create a scalar for each
|
|
(
|
|
|
|
SVN = scalarNames[i]
|
|
debugPrint ("SVN = "+(SVN as string))
|
|
|
|
scalContStr = (scalarConts[i] as string)
|
|
debugPrint ("scalCont = "+scalContStr)
|
|
scalCont = execute scalContStr
|
|
|
|
|
|
newfcStr.AddScalarTarget SVN scalCont --add scalar pointing to the controller of the scalar object
|
|
)
|
|
)
|
|
|
|
--format ("setting expression to :\r\n"+expString+"\n")
|
|
|
|
newfcStr.SetExpression expString
|
|
|
|
debugPrint ("Expression created on "+expObj+" for "+expCont)
|
|
debugPrint "```````````````````````````````````````````````````````"
|
|
)
|
|
else
|
|
(
|
|
--first test if theres a scaleOffsetJoystick and if not merge it in
|
|
|
|
offsetJS = getNodeByName "ScaleOffset"
|
|
|
|
if offsetJS == undefined do
|
|
(
|
|
mergeMaxFile rsOffsetJSFile
|
|
)
|
|
|
|
offsetJS = getNodeByName "ScaleOffset"
|
|
if offsetJS != undefined then
|
|
(
|
|
setUserPropBuffer offsetJS "exportTrans = true"
|
|
|
|
in coordsys parent offsetJS.position.controller[2].Y_position = -1
|
|
)
|
|
|
|
expString = ("("+expString+")")
|
|
|
|
debugPrint "----------------------------------------------------------------------------"
|
|
debugPrint "\r\n"
|
|
debugPrint ("Creating expression on "+expObj+". Scalar of "+(scalarObjects as string))
|
|
debugPrint ("Using expression:")
|
|
debugPrint expString
|
|
debugPrint "\r\n"
|
|
debugPrint "----------------------------------------------------------------------------"
|
|
|
|
fcStr = ( "$"+expObj+expCont) --rebuild the string so it can be used below
|
|
local newfcStr = execute fcStr
|
|
debugPrint ("newfcStr = "+(fcStr as string))
|
|
|
|
if scalarNames.count != 0 do
|
|
(
|
|
for i = 1 to scalarNames.count do --this should loop through the array of scalars and their controllers and create a scalar for each
|
|
(
|
|
|
|
SVN = scalarNames[i]
|
|
debugPrint ("SVN = "+(SVN as string))
|
|
|
|
scalContStr = (scalarConts[i] as string)
|
|
debugPrint ("scalCont = "+scalContStr)
|
|
scalCont = execute scalContStr
|
|
|
|
|
|
newfcStr.AddScalarTarget SVN scalCont --add scalar pointing to the controller of the scalar object
|
|
)
|
|
)
|
|
|
|
debugPrint ("setting expression to :\r\n"+expString)
|
|
|
|
newfcStr.SetExpression expString
|
|
|
|
debugPrint ("Expression created on "+expObj+" for "+expCont)
|
|
debugPrint "```````````````````````````````````````````````````````"
|
|
)
|
|
)
|
|
|
|
fn removeOldScaleControllers thisBone =
|
|
(
|
|
contCount = thisBone.scale.controller.count
|
|
for i = (contCount - 1) to 1 by -1 do
|
|
(
|
|
thisCont = thisBone.Scale.controller[i]
|
|
|
|
if thisCont = thisBone.Scale.controller[i].name != "ConcatScale" then
|
|
(
|
|
if thisCont = thisBone.Scale.controller[i].name != "Frozen Scale" then
|
|
(
|
|
if thisCont = thisBone.Scale.controller[i].name != "Zero Scale XYZ" then
|
|
(
|
|
--ok we can remove this controller
|
|
debugprint ("Deleting "+thisBone.Scale.controller[i].name+" from "+thisBone.name)
|
|
thisBone.scale.controller.delete i
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
fn concatScale thisBone scaleAxis spclCaseConCat =
|
|
(
|
|
generateScaleOffsetNode = false
|
|
--need to put a test in here for if we are a concat-able facial joint
|
|
|
|
--if spclCaseConCat == true then we dont want to add a +1 to the concatenation
|
|
|
|
debugprint ("Concatting "+scaleAxis+" on "+thisBone.name)
|
|
contCount = thisBone.scale.controller.count
|
|
|
|
sclrName = #()
|
|
sclrObjs = #()
|
|
sclrCont = #()
|
|
expStr = #()
|
|
driverValue = #()
|
|
|
|
for c = 2 to contCount do
|
|
(
|
|
contStr = ("$"+thisBone.name+".scale.controller["+(c as string)+"]."+scaleAxis+".controller")
|
|
|
|
cont = execute contStr
|
|
if (cont as string) == "Controller:Float_Expression" do
|
|
(
|
|
--need to get number of scalars and then loop through those
|
|
myScalarCount = cont.NumScalars()
|
|
|
|
for nScl = 5 to myScalarCount do
|
|
(
|
|
myScalarName = cont.GetScalarName nScl --index of 5 thanks to the ticks, secs, nt and f variables always present
|
|
myScalarObj = cont.getScalarTarget myScalarName asController:false
|
|
|
|
myScalarObj = exprForMAXObject myScalarObj
|
|
filteredStr = filterString myScalarObj "."
|
|
myScalarObj = filteredStr[1]
|
|
|
|
myScalarCont = cont.getScalarTarget myScalarName asController:true
|
|
myScalarCont = exprForMAXObject myScalarCont
|
|
|
|
myDriverValStr = (filterstring myScalarCont ".controller")
|
|
myDriverVal = (myDriverValStr[1])
|
|
|
|
toRemoveStr = ".controller"
|
|
toRemoveCount = toRemoveStr.count
|
|
contCharCount = myScalarCont.count
|
|
finalDriv = substring myScalarCont 1 (contCharCount - toRemoveCount)
|
|
myDriverVal = execute finalDriv
|
|
debugprint ("myDriverVal = "+(myDriverVal as string))
|
|
|
|
myExpression = cont.GetExpression()
|
|
--*** MAY NEED TO DFO A FUNKY WAY OF APPENDING IF UNIQUE HERE
|
|
append SclrName (myScalarName as string)
|
|
append sclrObjs (myScalarObj as string)
|
|
append sclrCont (myScalarCont as string)
|
|
append expStr (myExpression as string)
|
|
append driverValue (myDriverVal as string)
|
|
)
|
|
|
|
--print ("myExpression["+(c as string)+"]: "+(myExpression as string))
|
|
)
|
|
)
|
|
|
|
--now need to see if the scalar driver value is a 0 or not. If its a zero then we need to add the +1 otherwise we dont
|
|
|
|
expString = undefined
|
|
offsetContIndex = undefined
|
|
foundOffset = false
|
|
|
|
expString = ""
|
|
for c = 1 to SclrName.count do
|
|
(
|
|
expString = (expString + (" + "+(expStr[c])))
|
|
--print ("Mid con: "+expString)
|
|
)
|
|
|
|
if spclCaseConCat == true then
|
|
(
|
|
expString = ("(ScaleOffset + 1) "+expString)
|
|
|
|
generateScaleOffsetNode = true
|
|
)
|
|
else
|
|
(
|
|
expString = ("1 "+expString)
|
|
|
|
generateScaleOffsetNode = false
|
|
)
|
|
|
|
for a = 1 to contCount do
|
|
(
|
|
if thisBone.scale.controller[a].name == "ConcatScale" do
|
|
(
|
|
foundOffset = true
|
|
offsetContIndex = a
|
|
--now add a float expression
|
|
concatCtrlStr = ("$"+thisBone.name+".scale.controller["+(offsetContIndex as string)+"]."+scaleAxis+".controller = Float_Expression ()")
|
|
execute concatCtrlStr
|
|
)
|
|
)
|
|
|
|
if foundOffset == false do
|
|
(
|
|
thisBone.scale.controller.available.controller = ScaleXYZ ()
|
|
thisBone.scale.controller.setName (contCount + 1) ("ConcatScale")
|
|
offsetContIndex = (contCount + 1)
|
|
concatCtrlStr = ("$"+thisBone.name+".scale.controller["+(offsetContIndex as string)+"]."+scaleAxis+".controller = Float_Expression ()")
|
|
execute concatCtrlStr
|
|
)
|
|
|
|
expObj = thisBone.name
|
|
|
|
expCont = (".scale.controller["+((offsetContIndex) as string)+"]."+scaleAxis+".controller")
|
|
|
|
scalarObjects = sclrObjs
|
|
scalarNames = sclrName
|
|
scalarConts = sclrCont
|
|
|
|
|
|
if findString expObj "Analog" != undefined do
|
|
(
|
|
--format ("Testing "+expObj+" for scale drivers..."+"\n")
|
|
foundScale = undefined
|
|
for i in scalarConts do
|
|
(
|
|
if findString i "cale" != undefined do
|
|
(
|
|
foundScale = true
|
|
)
|
|
)
|
|
|
|
if foundScale == true do
|
|
(
|
|
expString = scaleFixUpScaleByScale expString
|
|
)
|
|
)
|
|
|
|
generateExpressionIM expObj expCont scalarObjects scalarNames scalarConts expString
|
|
)
|
|
|
|
fn prepScaleOffset =
|
|
(
|
|
--first we get all the joints in the skin modifier
|
|
geoName = geoNames[2][1]
|
|
geoObj = getNodeByNameWildcard geoName
|
|
thisSkin = geoObj.modifiers[#Skin]
|
|
|
|
theseBoneNames = #()
|
|
|
|
for o in objects do
|
|
(
|
|
if (substring o.name 1 6) == "FACIAL" do
|
|
(
|
|
appendIfUnique theseBoneNames o.name
|
|
)
|
|
if (substring o.name 1 4) == "SKEL" do
|
|
(
|
|
appendIfUnique theseBoneNames o.name
|
|
)
|
|
)
|
|
|
|
|
|
|
|
for i = 1 to theseBoneNames.count do
|
|
(
|
|
spclCaseConCat = false
|
|
|
|
thisBone = getNodeByName theseBoneNames[i]
|
|
|
|
if (classof thisBone.scale.controller as string) == "scale_list" do
|
|
(
|
|
if thisBone.scale.controller.count > 2 do
|
|
(
|
|
concatThis = true
|
|
|
|
for nc = 1 to nonConcatJoints.count do
|
|
(
|
|
if thisBone.name == nonConcatJoints[nc] do
|
|
(
|
|
-- concatThis = false
|
|
concatThis = TRUE
|
|
|
|
spclCaseConCat = true
|
|
)
|
|
)
|
|
|
|
if concatThis == true do
|
|
(
|
|
--now we need to check all existing controllers and see if they are x y or z so we know if we need to add a correspondig offset
|
|
xCont = false
|
|
yCont = false
|
|
zCont = false
|
|
|
|
for c = 2 to thisBone.scale.controller.count do
|
|
(
|
|
xC = thisBone.scale.controller[c].X_Scale.controller
|
|
yC = thisBone.scale.controller[c].Y_Scale.controller
|
|
zC = thisBone.scale.controller[c].Z_Scale.controller
|
|
|
|
if (xC as string) == "Controller:Float_Expression" do
|
|
(
|
|
xCont = true
|
|
)
|
|
if (yC as string) == "Controller:Float_Expression" do
|
|
(
|
|
yCont = true
|
|
)
|
|
if (zC as string) == "Controller:Float_Expression" do
|
|
(
|
|
zCont = true
|
|
)
|
|
)
|
|
|
|
if xCont == true do
|
|
(
|
|
concatScale thisBone "X_Scale" spclCaseConCat
|
|
)
|
|
if yCont == true do
|
|
(
|
|
concatScale thisBone "Y_Scale" spclCaseConCat
|
|
)
|
|
if zCont == true do
|
|
(
|
|
concatScale thisBone "Z_Scale" spclCaseConCat
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
fn FreezeTransform = --freezes transforms. Copied from the max macroscript as this does not like being run from other scripts.
|
|
(
|
|
local Obj = Selection as array
|
|
suspendEditing which:#motion
|
|
for i = 1 to Obj.count do
|
|
(
|
|
Try
|
|
(
|
|
local CurObj = Obj[i]
|
|
|
|
if classof CurObj.rotation.controller != Rotation_Layer do
|
|
(
|
|
-- freeze rotation
|
|
CurObj.rotation.controller = Euler_Xyz()
|
|
CurObj.rotation.controller = Rotation_list()
|
|
CurObj.rotation.controller.available.controller = Euler_xyz()
|
|
|
|
/* "Localization on" */
|
|
|
|
CurObj.rotation.controller.setname 1 "Frozen Rotation"
|
|
CurObj.rotation.controller.setname 2 "Zero Euler XYZ"
|
|
|
|
/* "Localization off" */
|
|
|
|
CurObj.rotation.controller.SetActive 2
|
|
)
|
|
if classof CurObj.position.controller != Position_Layer do
|
|
(
|
|
-- freeze position
|
|
CurObj.position.controller = Bezier_Position()
|
|
CurObj.position.controller = position_list()
|
|
CurObj.position.controller.available.controller = Position_XYZ()
|
|
|
|
/* "Localization on" */
|
|
|
|
CurObj.position.controller.setname 1 "Frozen Position"
|
|
CurObj.position.controller.setname 2 "Zero Pos XYZ"
|
|
|
|
/* "Localization off" */
|
|
|
|
CurObj.position.controller.SetActive 2
|
|
|
|
-- position to zero
|
|
CurObj.Position.controller[2].x_Position = 0
|
|
CurObj.Position.controller[2].y_Position = 0
|
|
CurObj.Position.controller[2].z_Position = 0
|
|
)
|
|
if classof CurObj.scale.controller != Scale_Layer do
|
|
(
|
|
-- freeze scale
|
|
CurObj.scale.controller = Bezier_Scale()
|
|
CurObj.scale.controller = scale_list()
|
|
CurObj.scale.controller.available.controller = ScaleXYZ()
|
|
|
|
/* "Localization on" */
|
|
|
|
CurObj.scale.controller.setname 1 "Frozen Scale"
|
|
CurObj.scale.controller.setname 2 "Zero Scale XYZ"
|
|
|
|
/* "Localization off" */
|
|
|
|
CurObj.scale.controller.SetActive 2
|
|
|
|
-- scale to zero
|
|
CurObj.scale.controller[2].x_Scale = 100
|
|
CurObj.scale.controller[2].y_Scale = 100
|
|
CurObj.scale.controller[2].z_Scale = 100
|
|
)
|
|
|
|
)
|
|
/* "Localization on" */
|
|
|
|
Catch( messagebox ("A failure occurred while freezing "+(Obj.name)+"'s transform." title:"Freeze Transform"))
|
|
|
|
/* "Localization off" */
|
|
)
|
|
resumeEditing which:#motion
|
|
)
|
|
|
|
|
|
|
|
fn clampCtrls = --sets joysticks to default clamp values
|
|
(
|
|
for i = 1 to frameCTRLNodes.count do
|
|
(
|
|
thisObj = getNodeByName frameCTRLNodes[i]
|
|
|
|
thisObj.pos.controller.Zero_Pos_XYZ.controller.X_Position.controller = float_limit ()
|
|
thisObj.pos.controller.Zero_Pos_XYZ.controller.Y_Position.controller = float_limit ()
|
|
thisObj.pos.controller.Zero_Pos_XYZ.controller.Z_Position.controller = float_limit ()
|
|
|
|
thisObj.pos.controller.Zero_Pos_XYZ.controller.X_Position.controller.upper_limit = 1
|
|
thisObj.pos.controller.Zero_Pos_XYZ.controller.X_Position.controller.lower_limit = -1
|
|
|
|
thisObj.pos.controller.Zero_Pos_XYZ.controller.Y_Position.controller.upper_limit = 1
|
|
thisObj.pos.controller.Zero_Pos_XYZ.controller.Y_Position.controller.lower_limit = -1
|
|
|
|
thisObj.pos.controller.Zero_Pos_XYZ.controller.Z_Position.controller.upper_limit = 0
|
|
thisObj.pos.controller.Zero_Pos_XYZ.controller.Z_Position.controller.lower_limit = 0
|
|
)
|
|
)
|
|
|
|
|
|
fn prepExpressionString expObj expCont scalarObjects scalarNames scalarConts expString =
|
|
(
|
|
initialString = expString
|
|
|
|
scalarNamesLength = scalarNames[1].count
|
|
substit = (substring scalarNames[1] (scalarNamesLength - 2) 3)
|
|
|
|
if substit == "Rot" do
|
|
(
|
|
stringToReplace = scalarNames[1]
|
|
replaceToString = (" radToDeg ("+stringToReplace+")" )
|
|
initialString = substituteString initialString stringToReplace replaceToString
|
|
)
|
|
|
|
formattIngStr = ("\r\n"+" + ")
|
|
replaceString = "+"
|
|
|
|
|
|
expString = substituteString initialString replaceString formattingStr
|
|
|
|
debugprint "---------------------------"
|
|
debugprint expString
|
|
debugprint "---------------------------"
|
|
|
|
debugprint ("expCont = "+expCont)
|
|
|
|
generateExpressionIM expObj expCont scalarObjects scalarNames scalarConts expString
|
|
)
|
|
|
|
fn parseScaleStrForNumbers expString countFrom =
|
|
(
|
|
numVals = #(
|
|
"1",
|
|
"2",
|
|
"3",
|
|
"4",
|
|
"5",
|
|
"6",
|
|
"7",
|
|
"8",
|
|
"9",
|
|
"0",
|
|
"."
|
|
)
|
|
|
|
--print ("Passed to fullParse")
|
|
|
|
--print ("CountFrom = "+(countFrom as string))
|
|
stringLength = expString.count
|
|
--print ("stringLength = "+(stringLength as string))
|
|
firstNumFound = undefined
|
|
secondNumFound = undefined
|
|
|
|
|
|
returnData[3] = countFrom
|
|
|
|
for cnt = countFrom to stringLength do
|
|
(
|
|
if firstNumFound == undefined then
|
|
(
|
|
if (expString[cnt] == numVals[1]) or (expString[cnt] == numVals[2]) or (expString[cnt] == numVals[3]) or (expString[cnt] == numVals[4]) or (expString[cnt] == numVals[5]) or (expString[cnt] == numVals[6]) or (expString[cnt] == numVals[7]) or (expString[cnt] == numVals[8]) or (expString[cnt] == numVals[9]) or (expString[cnt] == numVals[10]) or (expString[cnt] == numVals[11]) do
|
|
(
|
|
firstNumFound = cnt
|
|
--print ("firstNumSet to "+(cnt as string))
|
|
)
|
|
)
|
|
else
|
|
(
|
|
--ok so we found the first num Value so we need to count from there
|
|
if secondNumFound == undefined then
|
|
(
|
|
for cnt = firstNumFound to stringLength do
|
|
(
|
|
if (expString[cnt] == numVals[1]) or (expString[cnt] == numVals[2]) or (expString[cnt] == numVals[3]) or (expString[cnt] == numVals[4]) or (expString[cnt] == numVals[5]) or (expString[cnt] == numVals[6]) or (expString[cnt] == numVals[7]) or (expString[cnt] == numVals[8]) or (expString[cnt] == numVals[9]) or (expString[cnt] == numVals[10]) or (expString[cnt] == numVals[11]) then
|
|
(
|
|
--ok found a num so carry on
|
|
)
|
|
else
|
|
(
|
|
secondNumFound = cnt
|
|
--now we need to replace the from and to to a new number.
|
|
|
|
fromVal = firstNumFound
|
|
toVal = (secondNumFound - firstNumFound)
|
|
strToChange = ((substring expString fromVal toVal ) as float)
|
|
----print (strToChange as string)
|
|
newStr = (strToChange + 1)
|
|
|
|
----print ("old:"+expString)
|
|
expString = replace expString firstNumFound (secondNumFound - firstNumFound) (newStr as string)
|
|
----print ("new:"+expString)
|
|
countFrom = (secondNumFound + 1)
|
|
|
|
returnData[1] = expString
|
|
returnData[2] = countFrom
|
|
|
|
return returnData
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
fn preParseScaleExpr expString countFrom expObj expCont scalarObjects scalarNames scalarConts =
|
|
(
|
|
while returnData[2] != returnData[3] do
|
|
(
|
|
--print ("Found returned data")
|
|
expString = returnData[1]
|
|
countFrom = returnData[2]
|
|
|
|
parseScaleStrForNumbers expString countFrom
|
|
)
|
|
|
|
--print "Creating scale offset expression"
|
|
expString = returnData[1]
|
|
prepExpressionString expObj expCont scalarObjects scalarNames scalarConts expString
|
|
)
|
|
|
|
--this function takes the parsed data from the xml and then prepares it so it can be passed to the generateExpressionIM function
|
|
fn prepStringForExpression expObj expCont expString scalarObjects scalarNames scalarConts facialRollout =
|
|
(
|
|
-- initDebugVal = debugPrintVal
|
|
-- if expObj == "upperLip_L_OFF" then
|
|
-- (
|
|
-- debugPrintVal = true
|
|
--
|
|
-- format ("::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n")
|
|
-- )
|
|
|
|
axisToUse = (substring expCont 1 1)
|
|
transType = (substring expCont 3 50)
|
|
|
|
--firstly need to add a controller to the stack with the name of the first scalarName.
|
|
debugPrint ("trying to get node "+expObj)
|
|
|
|
expressionObj = getNodeByName expObj
|
|
|
|
appendIfUnique rigBones expressionObj
|
|
|
|
if expressionObj == undefined then
|
|
(
|
|
--print ("SSSSSSSSSSSSSSSSSHHHHHHHHHHHHHHHHHIT. Couldnt find "+expObj)
|
|
)
|
|
else
|
|
(
|
|
|
|
if (expressionObj.position.controller as string) != "Controller:Position_List" do
|
|
(
|
|
expressionObj.position.controller = Position_List ()
|
|
expressionObj.rotation.controller = Rotation_List ()
|
|
expressionObj.scale.controller = Scale_List ()
|
|
)
|
|
|
|
controllerCount = ("$"+expObj+"."+transType+".controller."+"count")
|
|
controllerCount = execute controllerCount
|
|
|
|
myBoneObj = getNodeByName expObj
|
|
|
|
|
|
foundCont = false
|
|
|
|
contName = scalarNames[1]
|
|
ctrlCountStr = ("$"+myBoneObj.name+"."+transType+".controller.count")
|
|
ctrlCount = execute ctrlCountStr
|
|
|
|
for i = ctrlCount to 1 by -1 do
|
|
(
|
|
myContStr = ("$"+myBoneObj.name+"."+transType+".controller["+(i as string)+"].name")
|
|
myContName = execute myContStr
|
|
if myContName == (contName) do
|
|
(
|
|
debugPrint ("Found "+transType+" on "+("$"+myBoneObj.name+"."+transType+".controller"))
|
|
foundCont = true
|
|
)
|
|
)
|
|
|
|
controllerCount = ("$"+expObj+"."+transType+".controller."+"count")
|
|
controllerCount = execute controllerCount
|
|
|
|
if foundCont == false then
|
|
(
|
|
if transType == "Rotation" then
|
|
(
|
|
expContForMaxStr = ("$"+expObj+"."+transType+".controller."+"available.controller = Euler_XYZ ()")
|
|
--debugPrint ("executing: "+expContForMaxStr)
|
|
expContForMax = execute expContForMaxStr
|
|
)
|
|
else
|
|
(
|
|
if transType == "Position" then
|
|
(
|
|
expContForMaxStr = ("$"+expObj+"."+transType+".controller."+"available.controller = Position_XYZ ()")
|
|
--debugPrint ("executing: "+expContForMaxStr)
|
|
expContForMax = execute expContForMaxStr
|
|
)
|
|
else
|
|
(
|
|
expContForMaxStr = ("$"+expObj+"."+transType+".controller."+"available.controller = ScaleXYZ ()")
|
|
--debugPrint ("executing: "+expContForMaxStr)
|
|
expContForMax = execute expContForMaxStr
|
|
)
|
|
)
|
|
|
|
expContForMaxStr = ("$"+expObj+"."+transType+".controller.setName "+((controllerCount + 1) as string)+" "+"\""+scalarNames[1]+"\"")
|
|
--debugPrint ("executing: "+expContForMaxStr)
|
|
execute expContForMaxStr
|
|
|
|
expContForMaxStr = ("$"+expObj+"."+transType+".controller["+((controllerCount + 1) as string)+"]."+expCont+".controller = Float_Expression ()")
|
|
--debugPrint ("executing: "+expContForMaxStr)
|
|
execute expContForMaxStr
|
|
|
|
|
|
expCont = ("."+transType+".controller["+((controllerCount + 1) as string)+"]."+expCont+".controller")
|
|
)
|
|
else
|
|
(
|
|
debugPrint ("scalarNames[1] = "+(scalarNames[1]))
|
|
debugPrint ("transType = "+transType)
|
|
debugPrint ("expCont = "+expCont)
|
|
debugPrint (" fullStr="+ ("."+transType+".controller."+(scalarNames[1])+"."+expCont+".controller"))
|
|
|
|
expContForMaxStr = ("$"+expObj+"."+transType+".controller."+(scalarNames[1])+"."+expCont+".controller = Float_Expression ()")
|
|
--debugPrint ("executing: "+expContForMaxStr)
|
|
execute expContForMaxStr
|
|
|
|
expCont = ("."+transType+".controller."+(scalarNames[1])+"."+expCont+".controller")
|
|
)
|
|
|
|
|
|
|
|
--now for each controller in the scalarConts array we need to build that controller string
|
|
|
|
for i = 1 to scalarConts.count do
|
|
(
|
|
if ((substring scalarConts[i] 1 1) == "c") or ((substring scalarConts[i] 1 1) == "C") then
|
|
(
|
|
scalCont = (substring scalarConts[i] 3 200)
|
|
|
|
debugPrint "====================================================="
|
|
facialRollout = ("."+scalarObjects[i]+"_A")
|
|
debugPrint ("Attempting to use "+facialRollout+" with object "+scalarObjects[i])
|
|
tmpScalarCont = ("$"+scalarObjects[i]+".modifiers[#Attribute_Holder]"+facialRollout+"."+scalCont+"_CA.controller")
|
|
debugPrint ("---FOUND CUSTOM ATTR: "+tmpScalarCont )
|
|
scalarConts[i] = tmpScalarCont
|
|
)
|
|
else
|
|
(
|
|
axisToUse = (substring scalarConts[i] 1 1)
|
|
transType = (substring scalarConts[i] 3 50)
|
|
|
|
debugPrint ("scalarConts["+(i as string)+"] = "+scalarConts[i])
|
|
debugPrint ("transType = "+transType)
|
|
|
|
cType = undefined
|
|
|
|
if (transType == "Rotation") or (transType == "rotation") then
|
|
(
|
|
debugPrint "transType = Rotation"
|
|
ctype = "Zero_Euler_XYZ."
|
|
)
|
|
else
|
|
(
|
|
if (transType == "Position") or (transType == "position") then
|
|
(
|
|
debugPrint "transType = Position"
|
|
cType = "Zero_Pos_XYZ."
|
|
)
|
|
else
|
|
(
|
|
debugPrint "transType = Scale"
|
|
cType = "Zero_Scale_XYZ."
|
|
)
|
|
)
|
|
|
|
if useZeroControllers == false do
|
|
(
|
|
cType = "" --this will stop us from looking for a frozen controller
|
|
)
|
|
tmpScalarCont = ("$"+scalarObjects[i]+"."+transType+".controller."+cType+scalarConts[i]+".controller")
|
|
|
|
|
|
scalarConts[i] = tmpScalarCont
|
|
)
|
|
)
|
|
|
|
debugprint "\r\n"
|
|
|
|
debugPrint ("NEW scalarConts = "+(scalarConts as string))
|
|
|
|
prepExpressionString expObj expCont scalarObjects scalarNames scalarConts expString
|
|
)
|
|
|
|
-- debugPrintVal = initDebugVal
|
|
)
|
|
|
|
fn createCattRollout objName rolloutName attrName attrMin attrMax= --function to create attribute holder and custom attributes inisde it
|
|
(
|
|
--objName = string of object to receive the attribute holder
|
|
--rolloutName = string for name of rollout
|
|
--attrName = name of the attribute as seen in the UI
|
|
|
|
|
|
|
|
currentJoystick = getNodeByName objName
|
|
debugPrint ("currentJoystick = "+currentJoystick.name)
|
|
if currentJoystick.modifiers[#Attribute_Holder] == undefined do
|
|
(
|
|
addModifier currentJoystick (EmptyModifier())
|
|
debugPrint ("Added Attr holder to "+currentJoystick.name)
|
|
)
|
|
|
|
-- need to put a test in here for if the custom attribute already exists
|
|
|
|
facialMultipliersCA = (currentJoystick.name +"CA")
|
|
|
|
posVal = "1"
|
|
negval = "-1"
|
|
defaultVal = "0"
|
|
------------------------------------------------
|
|
rolloutCreateStr1 = (facialMultipliersCA +" = attributes "+rolloutName +"\n" +"(" +"\n" +"\t" +"parameters main rollout:params"+"\n" +"\t"+"(" )
|
|
|
|
rolloutCreateStr2 = "" --start as empty string
|
|
|
|
for i = 1 to attrName.count do
|
|
(
|
|
codeTrackName= (attrName[i]+"_CA") --name as seen inside the code and track view
|
|
|
|
cAttrName = attrName[i]--name as seen in the ui
|
|
|
|
rolloutCreateStr2 = (rolloutCreateStr2 +( "\n" +"\t" +"\t" +codeTrackName+" type:#float ui:" +codeTrackName+" default:" +defaultVal ))
|
|
)
|
|
|
|
rolloutCreateStr3 = ("\n"+"\t"+")"+"\n" +"\t" +"rollout params "+" \"" +rolloutName+"\"" +"\n" +"\t" +"(" )
|
|
|
|
rolloutCreateStr4 = ""
|
|
|
|
for i = 1 to attrName.count do
|
|
(
|
|
posVal = attrMax[i]
|
|
negVal = attrMin[i]
|
|
codeTrackName= (attrName[i]+"_CA") --name as seen inside the code and track view
|
|
|
|
cAttrName = attrName[i]--name as seen in the ui
|
|
|
|
rolloutCreateStr4 = (rolloutCreateStr4 +"\n" +"\t"+"\t" +"spinner "+codeTrackName+" \"" +cAttrName+"\"" +" "+"fieldwidth:40 range:["+(negVal as string)+","+(posVal as string)+","+(defaultVal as string)+"] type:#float" )
|
|
)
|
|
|
|
rolloutCreateStr5 = ("\n" +"\t" +")" +"\n" +")"+"\n" +"\n" +"\t" +"custAttributes.add $" +currentJoystick.name+".modifiers[#'Attribute holder'] "+facialMultipliersCA)
|
|
|
|
rolloutCreation = (rolloutCreateStr1 + rolloutCreateStr2 + rolloutCreateStr3 +rolloutCreateStr4 +rolloutCreateStr5)
|
|
|
|
debugprint ("rolloutCreation should do:")
|
|
debugprint rolloutCreation
|
|
execute rolloutCreation
|
|
|
|
--now add bezier floats controllers to these attributes
|
|
|
|
for i = 1 to attrName.count do
|
|
(
|
|
codeTrackName= (attrName[i]+"_CA") --name as seen inside the code and track view
|
|
|
|
cont1 = ("$"+currentJoystick.name+".modifiers[#Attribute_Holder]."+rolloutName+"."+codeTrackName+".controller = bezier_float ()")
|
|
debugprint ("TRYING: "+cont1)
|
|
doneCont1 = execute cont1
|
|
if doneCont1 != undefined then
|
|
(
|
|
debugprint ("Custom Attribute created: "+("$"+currentJoystick.name+".modifiers[#Attribute_Holder]."+rolloutName+"."+codeTrackName+".controller"))
|
|
)
|
|
else
|
|
(
|
|
messagebox "FUCK SAKE! Couldnt make it" beep:true
|
|
)
|
|
)
|
|
|
|
)
|
|
|
|
fn parseXML =
|
|
(
|
|
rigBones = #()
|
|
|
|
if facialXmlFile == undefined do
|
|
(
|
|
facialXmlFile = getOpenFileName caption:"Facial XML File" types:"XML Data (*joint*.xml)|*joint*.xml|All Files (*.*)|*.*|"
|
|
)
|
|
|
|
debugPrint ("Picked "+facialXmlFile)
|
|
|
|
mappingXmlFile = facialXmlFile
|
|
xmlDoc = XmlDocument()
|
|
xmlDoc.init()
|
|
xmlDoc.load mappingXmlFile
|
|
xmlRoot = xmlDoc.document.DocumentElement
|
|
|
|
if facialXmlFile != undefined then
|
|
(
|
|
-- Parse the XML
|
|
dataElems = xmlRoot.childnodes
|
|
--print "Beginning XML Parse..."
|
|
|
|
if ((progBar != undefined) and (progBar.isDisplayed)) do
|
|
(destroyDialog progBar)
|
|
|
|
createDialog progBar width:400 Height:30
|
|
|
|
|
|
--bit hacky way of ensuring that attribute holders and their attributes do not get regenerated.
|
|
for i = 0 to (dataElems.Count - 1 ) do
|
|
(
|
|
a = ((dataElems.count as float) / 100)
|
|
progBar.prog.value = (1.*i/a)
|
|
|
|
objName = undefined
|
|
rolloutName = undefined
|
|
attrName = #()
|
|
attrMin = #()
|
|
attrMax = #()
|
|
|
|
expObj = undefined
|
|
expCont = undefined
|
|
expString = undefined
|
|
scalarObjects = #()
|
|
scalarNames = #()
|
|
scalarConts = #()
|
|
facialRollout = ""
|
|
|
|
dataElement = dataElems.itemof(i)
|
|
debugPrint ("i = "+(i as string))
|
|
|
|
--need to do a pre-process here for all cAtt objects and delete existing attribute holders
|
|
|
|
if dataElement.name == "cAtt" do
|
|
(
|
|
elementAttrs = dataElement.attributes
|
|
debugPrint ("Found "+(elementAttrs.count as string)+" attributes")
|
|
|
|
for ea = 0 to (elementAttrs.count - 1 ) do
|
|
(
|
|
debugPrint (ea as string)
|
|
currentElem = elementAttrs.itemOf(ea)
|
|
|
|
debugPrint ("currentElem = "+(currentElem.name as string))
|
|
|
|
--now we can test for the values
|
|
if (currentElem.Name as string) == "objName" do
|
|
(
|
|
debugPrint (currentElem.Name+" matched "+"objName")
|
|
objName = (currentElem.value as string)
|
|
)
|
|
if (currentElem.Name as string) == "rolloutName" do
|
|
(
|
|
debugPrint (currentElem.Name+" matched "+"expCont")
|
|
rolloutName= (currentElem.value as string)
|
|
)
|
|
)
|
|
|
|
--now delete any old attribute modifiers and create a new one
|
|
|
|
currObj = getNodeByName objName
|
|
if currObj != undefined do
|
|
(
|
|
m = currObj.modifiers[#Attribute_Holder]
|
|
if m != undefined do
|
|
(
|
|
deleteModifier currObj m
|
|
)
|
|
|
|
addModifier currObj (EmptyModifier())
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
--now do the real stuff
|
|
for i = 0 to (dataElems.Count - 1 ) do
|
|
(
|
|
a = ((dataElems.count as float) / 100)
|
|
|
|
progBar.prog.value = (1.*i/a)
|
|
|
|
objName = undefined
|
|
rolloutName = undefined
|
|
attrName = #()
|
|
attrMin = #()
|
|
attrMax = #()
|
|
|
|
expObj = undefined
|
|
expCont = undefined
|
|
expString = undefined
|
|
scalarObjects = #()
|
|
scalarNames = #()
|
|
scalarConts = #()
|
|
facialRollout = ""
|
|
|
|
dataElement = dataElems.itemof(i)
|
|
debugPrint ("i = "+(i as string))
|
|
|
|
--need to do a pre-process here for all cAtt objects and delete existing attribute holders
|
|
|
|
if dataElement.name == "cAtt" do
|
|
(
|
|
elementAttrs = dataElement.attributes
|
|
debugPrint ("Found "+(elementAttrs.count as string)+" attributes")
|
|
|
|
for ea = 0 to (elementAttrs.count - 1 ) do
|
|
(
|
|
debugPrint (ea as string)
|
|
currentElem = elementAttrs.itemOf(ea)
|
|
|
|
debugPrint ("currentElem = "+(currentElem.name as string))
|
|
|
|
--now we can test for the values
|
|
if (currentElem.Name as string) == "objName" do
|
|
(
|
|
debugPrint (currentElem.Name+" matched "+"objName")
|
|
objName = (currentElem.value as string)
|
|
)
|
|
if (currentElem.Name as string) == "rolloutName" do
|
|
(
|
|
debugPrint (currentElem.Name+" matched "+"expCont")
|
|
rolloutName= (currentElem.value as string)
|
|
)
|
|
)
|
|
)
|
|
|
|
debugPrint ("dataElementName = "+(dataElement.name))
|
|
|
|
if dataElement.name == "cAtt" do
|
|
(
|
|
elementAttrs = dataElement.attributes
|
|
debugPrint ("Found "+(elementAttrs.count as string)+" attributes")
|
|
|
|
for ea = 0 to (elementAttrs.count - 1 ) do
|
|
(
|
|
debugPrint (ea as string)
|
|
currentElem = elementAttrs.itemOf(ea)
|
|
|
|
debugPrint ("currentElem = "+(currentElem.name as string))
|
|
|
|
--now we can test for the values
|
|
if (currentElem.Name as string) == "objName" do
|
|
(
|
|
debugPrint (currentElem.Name+" matched "+"objName")
|
|
objName = (currentElem.value as string)
|
|
)
|
|
if (currentElem.Name as string) == "rolloutName" do
|
|
(
|
|
debugPrint (currentElem.Name+" matched "+"expCont")
|
|
rolloutName= (currentElem.value as string)
|
|
)
|
|
)
|
|
|
|
--now we look at the children
|
|
dataElemChildren = dataElement.childNodes
|
|
debugPrint ("Found "+(dataElemChildren.count as string)+" attributes.")
|
|
|
|
for c = 0 to (dataElemChildren.count - 1) do
|
|
(
|
|
--ok we're now looking at the driven for this node
|
|
childElement = dataElemChildren.itemOf[c]
|
|
childAttrs = childElement.attributes
|
|
|
|
for cA = 0 to (childAttrs.count - 1) do
|
|
(
|
|
currentChildElem = childAttrs.itemOf(cA)
|
|
debugPrint ("currentChildElem = "+(currentChildElem.name))
|
|
|
|
debugPrint ("found "+currentChildElem.name )
|
|
|
|
if currentChildElem.name == "attrName" do
|
|
(
|
|
--**** NEED TO STRIP OFF THE c_ ON THE START OF THE STRING
|
|
valToAppend = (substring currentChildElem.value 3 50)
|
|
append attrName (valToAppend as string)
|
|
debugprint "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
|
debugprint "\r"
|
|
debugPrint ("adding "+valToAppend+" to attrName array...")
|
|
debugPrint ("attrName count = "+(attrName.count as string))
|
|
debugprint "\r"
|
|
debugprint "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
|
|
)
|
|
|
|
if currentChildElem.name == "attrMin" do
|
|
(
|
|
append attrMin currentChildElem.value
|
|
)
|
|
|
|
if currentChildElem.name == "attrMax" do
|
|
(
|
|
append attrMax currentChildElem.value
|
|
)
|
|
)
|
|
)
|
|
debugprint ("count A = "+(attrName.count as string))
|
|
--run the create rollout here
|
|
debugprint ("objName = "+objName)
|
|
debugprint ("rolloutName = "+rolloutName)
|
|
debugprint ("attrName = "+(attrName as string))
|
|
clearSelection()
|
|
createCattRollout objName rolloutName attrName attrMin attrMax
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if dataElement.name == "driven" do
|
|
(
|
|
--ok now we need to query the attributes of this node
|
|
elementAttrs = dataElement.attributes
|
|
debugPrint ("Found "+(elementAttrs.count as string)+" attributes")
|
|
|
|
for ea = 0 to (elementAttrs.count - 1 ) do
|
|
(
|
|
debugPrint (ea as string)
|
|
currentElem = elementAttrs.itemOf(ea)
|
|
|
|
debugPrint ("currentElem = "+(currentElem.name as string))
|
|
|
|
--now we can test for the values
|
|
if (currentElem.Name as string) == "expObj" do
|
|
(
|
|
debugPrint (currentElem.Name+" matched "+"expObj")
|
|
expObj = currentElem.value
|
|
)
|
|
if (currentElem.Name as string) == "expCont" do
|
|
(
|
|
debugPrint (currentElem.Name+" matched "+"expCont")
|
|
expCont = currentElem.value
|
|
)
|
|
if (currentElem.Name as string) == "expString" do
|
|
(
|
|
debugPrint (currentElem.Name+" matched "+"expString")
|
|
expString = currentElem.value
|
|
)
|
|
)
|
|
|
|
|
|
--------------------------------------------------------------------------------------------------------
|
|
--------------------------------------------------------------------------------------------------------
|
|
--now we look at the children
|
|
dataElemChildren = dataElement.childNodes
|
|
debugPrint ("\r\n"+"Found "+(dataElemChildren.count as string)+" attributes.")
|
|
|
|
for c = 0 to (dataElemChildren.count - 1) do
|
|
(
|
|
--ok we're now looking at the driven for this node
|
|
childElement = dataElemChildren.itemOf[c]
|
|
childAttrs = childElement.attributes
|
|
debugPrint ("c = "+(c as string))
|
|
for cA = 0 to (childAttrs.count - 1) do
|
|
(
|
|
-- I CAN DO A TEST TO SEE THE COUNT OF CA AND IF ITS 4 WE
|
|
--KNOW ITS A CUSTOM ATTR SO MAYBE THAT WAY WE CAN DO THEM FIRST?
|
|
|
|
debugPrint ("cA = "+(cA as string))
|
|
currentChildElem = childAttrs.itemOf(cA)
|
|
debugPrint "-------------------------------------------------------------------------------------"
|
|
debugPrint ("**** currentChildElem = "+(currentChildElem.name))
|
|
|
|
if currentChildElem.name == "scalarObjects" do
|
|
(
|
|
append scalarObjects currentChildElem.value
|
|
debugPrint ("adding "+currentChildElem.value+" to scalarObjects array...")
|
|
debugPrint ("scalarObjects count = "+(scalarObjects.count as string))
|
|
)
|
|
|
|
if currentChildElem.name == "scalarNames" do
|
|
(
|
|
append scalarNames currentChildElem.value
|
|
debugPrint ("adding "+currentChildElem.value+" to scalarNames array...")
|
|
debugPrint ("scalarNames count = "+(scalarNames.count as string))
|
|
)
|
|
|
|
if currentChildElem.name == "scalarConts" do
|
|
(
|
|
append scalarConts currentChildElem.value
|
|
debugPrint ("adding "+currentChildElem.value+" to scalarConts array...")
|
|
debugPrint ("scalarConts count = "+(scalarConts.count as string))
|
|
)
|
|
|
|
if currentChildElem.name == "rolloutName" do
|
|
(
|
|
facialRollout = ("."+currentChildElem.value)
|
|
debugPrint ("facialRollout = "+(currentChildElem.value as string))
|
|
)
|
|
)
|
|
)
|
|
debugPrint "-----------------------------------------------------------------------"
|
|
debugPrint ("expObj = "+expObj)
|
|
debugPrint ("expCont = "+expCont)
|
|
debugPrint ("expStr = "+expString)
|
|
debugPrint ("scalarObjects = "+scalarObjects as string)
|
|
debugPrint ("scalarNames = "+scalarNames as string)
|
|
debugPrint ("scalarConts = "+scalarConts as string)
|
|
debugPrint ("facialRollout = "+facialRollout as string)
|
|
debugPrint "-----------------------------------------------------------------------"
|
|
prepStringForExpression expObj expCont expString scalarObjects scalarNames scalarConts facialRollout
|
|
)
|
|
)
|
|
|
|
if ((progBar != undefined) and (progBar.isDisplayed)) do
|
|
(destroyDialog progBar)
|
|
|
|
prepScaleOffset()
|
|
|
|
for tb = 1 to rigBones.count do
|
|
(
|
|
spclCase = false
|
|
thisBone = rigBones[tb]
|
|
if thisBone != undefined then
|
|
(
|
|
--need to ensure we dont remove controllers on the nonConcatJoints as they arent concatted
|
|
concatThis = true
|
|
|
|
for nc = 1 to nonConcatJoints.count do
|
|
(
|
|
if thisBone.name == nonConcatJoints[nc] do
|
|
(
|
|
--concatThis = false
|
|
)
|
|
)
|
|
|
|
if concatThis == true do
|
|
(
|
|
debugprint ("Running removeOldScaleControllers on "+thisBone.name)
|
|
removeOldScaleControllers thisBone
|
|
)
|
|
)
|
|
else
|
|
(
|
|
--print ("WARNING! Couldn't find "+(rigBones[tb] as string))
|
|
)
|
|
)
|
|
)
|
|
else
|
|
(
|
|
messagebox "Please select a valid xml file." Beep:true
|
|
)
|
|
)
|
|
|
|
-- use a callback to press the buttons
|
|
-- I found this here: http://forums.cgsociety.org/showthread.php?t=485300
|
|
fn LSW_FBXImportCallbackFunction =
|
|
(
|
|
WindowHandle = DialogMonitorOPS.GetWindowHandle()
|
|
theDialogName = UIAccessor.GetWindowText WindowHandle
|
|
|
|
if theDialogName != undefined and matchpattern theDialogName pattern:"*FBX Import*" do
|
|
UIAccessor.PressButtonByName WindowHandle "OK"
|
|
true
|
|
)
|
|
|
|
fn importSelectedFBX facialFBXFile autoClick =
|
|
(
|
|
-- Fix was from here: http://tech-artists.org/forum/showthread.php?p=4034
|
|
-- Use a callback to press the buttons
|
|
-- I found this here: http://forums.cgsociety.org/showthread.php?t=485300
|
|
|
|
if autoClick == true do
|
|
(
|
|
DialogMonitorOPS.RegisterNotification LSW_FBXImportCallbackFunction ID:#myFBXImporterFunction
|
|
DialogMonitorOPS.Enabled = true
|
|
)
|
|
|
|
--think i need to call the import here
|
|
-- pluginManager.loadClass FBXIMP
|
|
pluginManager.loadClass FBXIMPORTER
|
|
|
|
FbxImporterSetParam "Animation" false
|
|
|
|
FbxImporterSetParam "Shape" true
|
|
FbxImporterSetParam "Skin" true
|
|
-- FbxImporterSetParam "ImportBoneAsDummy"
|
|
|
|
FbxImporterSetParam "Mode" "merge"
|
|
-- FbxImporterSetParam "ScaleConversion" false
|
|
-- FbxImporterSetParam "ConvertUnit" "merge" "cm"
|
|
|
|
FbxImporterSetParam "ConvertUnit" "cm"
|
|
FbxImporterSetParam "ScaleFactor" 1.0
|
|
|
|
|
|
-- FbxImporterSetParam "ImportBoneAsDummy" false
|
|
|
|
|
|
importFile facialFBXFile using:FBXIMPORTER --have to do this with the #noPrompt flag turned off cos the fbx importer is buggy as shit and otherwise ignores the settings
|
|
|
|
if autoClick == true do
|
|
(
|
|
DialogMonitorOPS.Enabled = false
|
|
DialogMonitorOPS.UnRegisterNotification ID:#myFBXImporterFunction
|
|
)
|
|
|
|
)
|
|
|
|
fn addBonesToExpressionSet selectionSetName nodesToAdd =
|
|
(
|
|
|
|
expSet = selectionSets[selectionSetName]
|
|
tmpObjs = #()
|
|
|
|
if expSet != undefined then
|
|
(
|
|
for ss = 1 to expSet.count do
|
|
(
|
|
append tmpObjs expSet[ss]
|
|
)
|
|
)
|
|
else
|
|
(
|
|
expSet = #()
|
|
)
|
|
|
|
for ts = 1 to nodesToAdd.count do
|
|
(
|
|
appendIfUnique tmpObjs nodesToAdd[ts]
|
|
debugPrint ("adding "+nodesToAdd[ts].name+" to "+selectionSetName+" selection set")
|
|
)
|
|
|
|
deleteItem selectionSets selectionSetName
|
|
|
|
selectionSets[selectionSetName] = tmpObjs
|
|
)
|
|
|
|
fn addTags =
|
|
(
|
|
|
|
offFaceCTRLS = #($mouth_CTRL, $jaw_CTRL, $tongueMove_CTRL, $tongueRoll_CTRL, $tongueInOut_CTRL, $outerBrow_R_CTRL, $innerBrow_L_CTRL, $outerBrow_L_CTRL, $innerBrow_R_CTRL, $eye_C_CTRL, $eye_L_CTRL, $eye_R_CTRL, $nose_L_CTRL, $nose_R_CTRL, $cheek_L_CTRL, $cheek_R_CTRL)
|
|
|
|
mySel = #()
|
|
for o in objects do
|
|
(
|
|
oName = o.name
|
|
oNameLength = o.name.count
|
|
if (substring o.name 1 6) == "FACIAL" do
|
|
(
|
|
append mySel o
|
|
)
|
|
)
|
|
|
|
-- for o in offfaceCTRLS do
|
|
-- (
|
|
-- --COMMENTED OUT AS WE DONT WANT TO TAG CTRL OBJECTS
|
|
-- --appendIfUnique mySel o
|
|
-- )
|
|
|
|
format "initialising tag arrays... \n"
|
|
tagDataArray = RSTA_populateBoneTagMappingArray boneTagMappingXmlFile
|
|
format "tag arrays initialised.\n"
|
|
for b = 1 to mySel.count do
|
|
(
|
|
setUserPropBuffer mySel[b] "" --clear off any existing shit
|
|
if mySel[b].name == "SKEL_Head" then
|
|
(
|
|
bTag = RSTA_findBoneTag mySel[b].name tagDataArray
|
|
|
|
if bTag != "UNKNOWN" do
|
|
(
|
|
setUserProp mySel[b] "tag" bTag
|
|
)
|
|
setUserProp mySel[b] "exportTrans = " "False"
|
|
setUserProp mySel[b] "exportScale = " "False"
|
|
)
|
|
else
|
|
(
|
|
if mySel[b].name == "SKEL_Neck_1" then
|
|
(
|
|
bTag = RSTA_findBoneTag mySel[b].name tagDataArray
|
|
if bTag != "UNKNOWN" do
|
|
(
|
|
setUserProp mySel[b] "tag" bTag
|
|
)
|
|
setUserProp mySel[b] "exportTrans = " "False"
|
|
setUserProp mySel[b] "exportScale = " "False"
|
|
)
|
|
else
|
|
(
|
|
if mySel[b].name == "RB_Neck_1" then
|
|
(
|
|
bTag = RSTA_findBoneTag mySel[b].name tagDataArray
|
|
if bTag != "UNKNOWN" do
|
|
(
|
|
setUserProp mySel[b] "tag" bTag
|
|
)
|
|
setUserProp mySel[b] "exportTrans = " "False"
|
|
setUserProp mySel[b] "exportScale = " "False"
|
|
)
|
|
else
|
|
(
|
|
nameTag = ""
|
|
if mySel[b].name == "FACIAL_facialRoot" then
|
|
|
|
(nameTag = ("tag"+"FACIAL_facialRoot")
|
|
)
|
|
else
|
|
(
|
|
nameTag = ("tagBONETAG_"+mySel[b].name)
|
|
)
|
|
|
|
scaleTag = ("False")
|
|
transTag = ("False")
|
|
relScaleTag = "False"
|
|
|
|
if (mySel[b].scale.controller as string) == "Controller:Scale_List" DO
|
|
(
|
|
scaleContCount = mySel[b].scale.controller.count
|
|
|
|
for sc = 2 to scaleContCount do
|
|
(
|
|
if (classOf mySel[b].scale.controller[sc].X_Scale.controller as string) == "Float_Expression" do
|
|
(
|
|
scaleTag = "True"
|
|
relScaleTag = "true"
|
|
)
|
|
if (classOf mySel[b].scale.controller[sc].Y_Scale.controller as string) == "Float_Expression" do
|
|
(
|
|
scaleTag = "True"
|
|
relScaleTag = "true"
|
|
)
|
|
if (classOf mySel[b].scale.controller[sc].Z_Scale.controller as string) == "Float_Expression" do
|
|
(
|
|
scaleTag = "True"
|
|
relScaleTag = "true"
|
|
)
|
|
)
|
|
)
|
|
|
|
if (mySel[b].position.controller as string) != "Controller:Position_XYZ" do
|
|
(
|
|
transContCount = mySel[b].position.controller.count
|
|
|
|
for tc = 2 to transContCount do
|
|
(
|
|
if ((mySel[b].position.controller[tc]) as string) != "SubAnim:RsSpring" do
|
|
(
|
|
if (classOf mySel[b].position.controller[tc].X_Position.controller as string) == "Float_Expression" do
|
|
(
|
|
transTag = ("\r\n"+"exportTrans = True")
|
|
)
|
|
if (classOf mySel[b].position.controller[tc].Y_Position.controller as string) == "Float_Expression" do
|
|
(
|
|
transTag = ("\r\n"+"exportTrans = True")
|
|
)
|
|
if (classOf mySel[b].position.controller[tc].Z_Position.controller as string) == "Float_Expression" do
|
|
(
|
|
transTag = ("\r\n"+"exportTrans = True")
|
|
)
|
|
)
|
|
)
|
|
)
|
|
nameTag = RSTA_findBoneTag mySel[b].name tagDataArray
|
|
|
|
if mySel[b].name == "FACIAL_facialRoot" then
|
|
(
|
|
nameTag = ("FACIAL_facialRoot")
|
|
)
|
|
|
|
if nameTag != "UNKNOWN" do
|
|
(
|
|
setUserProp mySel[b] "tag" nameTag
|
|
)
|
|
|
|
setUserProp mySel[b] "exportTrans" transTag
|
|
setUserProp mySel[b] "exportScale" scaleTag
|
|
setUserProp mySel[b] "relScale" relScaleTag
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
--now tag the on face controls
|
|
tagOnFaceCtrls()
|
|
|
|
)
|
|
|
|
--called during full prep
|
|
fn prepSceneForMashup =
|
|
(
|
|
max unhide all
|
|
|
|
--first of all we need to merge into a new scene the GUI file
|
|
|
|
--so we need to pick it from somewhere
|
|
|
|
if facialGUIFile == undefined do
|
|
(
|
|
facialGUIFile = getOpenFileName caption:"Max GUI File" types:"Max Data (*.Max)|*.max|All Files (*.*)|*.*|"
|
|
)
|
|
|
|
if facialGUIFile != undefined do
|
|
(
|
|
--now we need to pick the fbx file with the mesh etc
|
|
|
|
if facialFbxFile == undefined do
|
|
(
|
|
facialFbxFile = getOpenFileName caption:"FBX Facial File" types:"FBX Data (*.FBX)|*.fbx|All Files (*.*)|*.*|"
|
|
)
|
|
|
|
if facialFbxFile != undefined do --ok we've picked the gui and mesh files so we can now go ahead and merge shit
|
|
(
|
|
if facialXmlFile == undefined do
|
|
(
|
|
facialXmlFile = getOpenFileName caption:"Facial XML File" types:"XML Data (*joint*.xml)|*joint*.xml|All Files (*.*)|*.*|"
|
|
)
|
|
|
|
currentObjects = objects as array
|
|
|
|
mergeMaxFile facialGUIFile
|
|
|
|
--now tag the on face controls
|
|
tagOnFaceCtrls()
|
|
|
|
--need to find all nodes added since the merge
|
|
postMergeObjs = objects as array
|
|
|
|
for cO = currentObjects.count to 1 by -1 do
|
|
(
|
|
for pM = postMergeObjs.count to 1 by -1 do
|
|
(
|
|
if currentObjects[cO] == postMergeObjs[pM] do
|
|
(
|
|
deleteItem postMergeObjs pM
|
|
)
|
|
)
|
|
)
|
|
|
|
controlGUIObjects = deepcopy postmergeObjs
|
|
|
|
for cGo = 1 to controlGUIObjects.count do
|
|
(
|
|
select controlGUIObjects[cGo]
|
|
FreezeTransform()
|
|
)
|
|
|
|
if useZeroControllers == true then
|
|
(
|
|
currentObjects = objects as array
|
|
|
|
unitSetting = FBXImporterGetParam "ConvertUnit"
|
|
|
|
if unitSetting != #cm then
|
|
(
|
|
messagebox ("FBX Importer not set to cm."+"\r\n"+"Please manually adjust and click ok.") beep:true
|
|
autoClick = false
|
|
)
|
|
else
|
|
(
|
|
autoClick = true
|
|
)
|
|
|
|
importSelectedFBX facialFBXFile autoClick --have to use a function with a callback so we can auto click the ok button
|
|
|
|
postMergeObjs = objects as array
|
|
|
|
for cO = currentObjects.count to 1 by -1 do
|
|
(
|
|
for pM = postMergeObjs.count to 1 by -1 do
|
|
(
|
|
if currentObjects[cO] == postMergeObjs[pM] do
|
|
(
|
|
deleteItem postMergeObjs pM
|
|
)
|
|
)
|
|
)
|
|
|
|
for i = 1 to postMergeObjs.count do
|
|
(
|
|
objectName = postMergeObjs[i].name
|
|
objectLength = objectName.count
|
|
if (substring postMergeObjs[i].name (objectLength - 3) 4) != "CTRL" do
|
|
(
|
|
select postMergeObjs[i]
|
|
FreezeTransform()
|
|
)
|
|
)
|
|
|
|
select postMergeObjs
|
|
|
|
newObjects = objects as array
|
|
nodesToAdd = #()
|
|
|
|
for nO = 1 to newObjects.count do
|
|
(
|
|
if (substring newObjects[nO].name 1 6) == "FACIAL" do
|
|
(
|
|
append nodesToAdd newObjects[nO]
|
|
)
|
|
)
|
|
|
|
--now need to tag too
|
|
addTags()
|
|
|
|
selectionSetName = "*EXPRESSIONS"
|
|
|
|
addBonesToExpressionSet selectionSetName nodesToAdd --this will add the facial bones to the *EXPRESSIONS selection set
|
|
)
|
|
else
|
|
(
|
|
currentObjects = objects as array
|
|
|
|
unitSetting = FBXImporterGetParam "ConvertUnit"
|
|
|
|
if unitSetting != #cm then
|
|
(
|
|
messagebox ("FBX Importer not set to cm."+"\r\n"+"Please manually adjust and click ok.") beep:true
|
|
autoClick = false
|
|
)
|
|
else
|
|
(
|
|
autoClick = true
|
|
)
|
|
importSelectedFBX facialFBXFile autoClick--have to use a function with a callback so we can auto click the ok button
|
|
|
|
postMergeObjs = objects as array
|
|
|
|
for cO = currentObjects.count to 1 by -1 do
|
|
(
|
|
for pM = postMergeObjs.count to 1 by -1 do
|
|
(
|
|
if currentObjects[cO] == postMergeObjs[pM] do
|
|
(
|
|
deleteItem postMergeObjs pM
|
|
)
|
|
)
|
|
)
|
|
|
|
select postMergeObjs
|
|
|
|
newObjects = selection as array
|
|
nodesToAdd = #()
|
|
|
|
for nO = 1 to newObjects.count do
|
|
(
|
|
if classOf newObjects[nO] != PolyMeshObject do
|
|
(
|
|
append nodesToAdd newObjects[nO]
|
|
)
|
|
)
|
|
|
|
selectionSetName = "*EXPRESSIONS"
|
|
|
|
addBonesToExpressionSet selectionSetName nodesToAdd --this will add the facial bones to the *EXPRESSIONS selection set
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
--function used when doing a simple clean scene prep
|
|
fn prepScene =
|
|
(
|
|
max unhide all
|
|
facialGUIFile = undefined
|
|
|
|
allObjects = objects as array
|
|
|
|
if facialGUIFile == undefined do
|
|
(
|
|
facialGUIFile = getOpenFileName caption:"Max GUI File" types:"Max Data (*.Max)|*.max|All Files (*.*)|*.*|"
|
|
)
|
|
|
|
if facialGUIFile != undefined do
|
|
(
|
|
--now we need to pick the fbx file with the mesh etc
|
|
|
|
facialFbxFile = undefined
|
|
|
|
if facialFbxFile == undefined do
|
|
(
|
|
facialFbxFile = getOpenFileName caption:"FBX Facial File" types:"FBX Data (*.FBX)|*.fbx|All Files (*.*)|*.*|"
|
|
)
|
|
|
|
if facialFbxFile != undefined do --ok we've picked the gui and mesh files so we can now go ahead and merge shit
|
|
(
|
|
facialXmlFile = undefined
|
|
|
|
if facialXmlFile == undefined do
|
|
(
|
|
facialXmlFile = getOpenFileName caption:"Facial XML File" types:"XML Data (*joint*.xml)|*joint*.xml|All Files (*.*)|*.*|"
|
|
|
|
originalObjects = objects as array
|
|
|
|
mergeMaxFile facialGUIFile
|
|
|
|
if useZeroControllers == true then
|
|
(
|
|
unitSetting = FBXImporterGetParam "ConvertUnit"
|
|
|
|
if unitSetting != #cm then
|
|
(
|
|
messagebox ("FBX Importer not set to cm."+"\r\n"+"Please manually adjust and click ok.") beep:true
|
|
autoClick = false
|
|
)
|
|
else
|
|
(
|
|
autoClick = true
|
|
)
|
|
|
|
importSelectedFBX facialFBXFile autoClick--have to use a function with a callback so we can auto click the ok button
|
|
|
|
currentObjects = objects as array
|
|
|
|
for i = 1 to currentObjects.count do
|
|
(
|
|
if (substring currentObjects[i].name 1 6) == "FACIAL" do
|
|
(
|
|
select currentObjects[i]
|
|
FreezeTransform()
|
|
)
|
|
)
|
|
newObjects = objects as array
|
|
|
|
--now find which are original objects and which have been merged in
|
|
|
|
for mO = newObjects.count to 1 by -1 do
|
|
(
|
|
for oo = 1 to originalObjects.count do
|
|
(
|
|
if originalObjects[oo] == newObjects[mO] do
|
|
(
|
|
deleteItem newObjects mO
|
|
)
|
|
)
|
|
)
|
|
nodesToAdd = #()
|
|
|
|
for nO = 1 to newObjects.count do
|
|
(
|
|
if classOf newObjects[nO] != PolyMeshObject do
|
|
(
|
|
append nodesToAdd newObjects[nO]
|
|
)
|
|
)
|
|
|
|
selectionSetName = "*EXPRESSIONS"
|
|
|
|
addBonesToExpressionSet selectionSetName nodesToAdd --this will add the facial bones to the *EXPRESSIONS selection set
|
|
)
|
|
else --ok we're not using zeroed controllers
|
|
(
|
|
currentObjects = objects as array
|
|
|
|
unitSetting = FBXImporterGetParam "ConvertUnit"
|
|
|
|
if unitSetting != #cm then
|
|
(
|
|
messagebox ("FBX Importer not set to cm."+"\r\n"+"Please manually adjust and click ok.") beep:true
|
|
autoClick = false
|
|
)
|
|
else
|
|
(
|
|
autoClick = true
|
|
)
|
|
|
|
importSelectedFBX facialFBXFile autoClick--have to use a function with a callback so we can auto click the ok button
|
|
|
|
select currentObjects
|
|
max select invert
|
|
|
|
newObjects = selection as array
|
|
nodesToAdd = #()
|
|
|
|
for nO = 1 to newObjects.count do
|
|
(
|
|
if classOf newObjects[nO] != PolyMeshObject do
|
|
(
|
|
append nodesToAdd newObjects[nO]
|
|
)
|
|
)
|
|
|
|
selectionSetName = "*EXPRESSIONS"
|
|
|
|
addBonesToExpressionSet selectionSetName nodesToAdd --this will add the facial bones to the *EXPRESSIONS selection set
|
|
)
|
|
)
|
|
)
|
|
|
|
parsexml()
|
|
|
|
for i = 1 to geoNames[2].count do
|
|
(
|
|
--hack
|
|
head = getNodeByName geoNames[2][1]
|
|
--end hack
|
|
if head != undefined do
|
|
(
|
|
head.modifiers[#Skin].always_deform = false
|
|
head.modifiers[#Skin].always_deform = true
|
|
)
|
|
)
|
|
)
|
|
|
|
)
|
|
|
|
fn createNormalsJoystick jsname jpos =
|
|
(
|
|
jstyle = 2 -- 2 = vertical slider
|
|
foundJS = getnodeByName jsName
|
|
if foundJS == undefined then
|
|
(
|
|
debugprint (jsName+" not found so initialising creation...")
|
|
createJoystick jsname jstyle jpos 1
|
|
--now add animated normals track
|
|
|
|
thisJS = getNodeByName jsname
|
|
setUserPropBuffer thisJs ("translateTrackType=TRACK_ANIMATED_NORMAL_MAPS")
|
|
|
|
--now set params for text and joytstick bounding box thing to not be frozen as gray then freeze
|
|
surrBox = (getNodeByName ("RECT_"+jsName))
|
|
surrBox.showFrozenInGray = false
|
|
surrBox.isFrozen = true
|
|
textItem = (getNodeByName ("TEXT_"+jsName))
|
|
textItem.showFrozenInGray = false
|
|
textItem.isFrozen = true
|
|
|
|
--now add joysticks to expression set
|
|
|
|
selectionSetName = "*EXPRESSIONS"
|
|
|
|
thisJSArray = #()
|
|
append thisJSArray thisJS
|
|
|
|
addBonesToExpressionSet selectionSetName thisJSArray
|
|
)
|
|
else
|
|
(
|
|
debugprint (jsName+" found so skipping creation.")
|
|
)
|
|
)
|
|
|
|
|
|
fn parseNormalsXML =
|
|
(
|
|
jp = 0.5
|
|
jCount = 0
|
|
jHeight = 0
|
|
|
|
if normalsXmlFile == undefined do
|
|
(
|
|
normalsXmlFile = getOpenFileName caption:"Normals XML File" types:"XML Data (*slider*.xml)|*slider*.xml|All Files (*.*)|*.*|"
|
|
)
|
|
|
|
debugPrint ("Picked "+normalsXmlFile)
|
|
|
|
mappingXmlFile = normalsXmlFile
|
|
xmlDoc = XmlDocument()
|
|
xmlDoc.init()
|
|
xmlDoc.load mappingXmlFile
|
|
xmlRoot = xmlDoc.document.DocumentElement
|
|
|
|
if normalsXmlFile != undefined then
|
|
(
|
|
-- Parse the XML
|
|
dataElems = xmlRoot.childnodes
|
|
--print "Beginning Normal XML Parse..."
|
|
|
|
if ((progBar != undefined) and (progBar.isDisplayed)) do
|
|
(destroyDialog progBar)
|
|
|
|
createDialog progBar width:400 Height:30
|
|
|
|
for i = 0 to (dataElems.Count - 1 ) do
|
|
(
|
|
a = ((dataElems.count as float) / 100)
|
|
|
|
progBar.prog.value = (1.*i/a)
|
|
|
|
maskExpStringArray = #() --array of expression strings
|
|
maskNameArray = #() --array of mask textures
|
|
maskSliderArray = #() --array of sliders
|
|
maskDriverSpnObjArray = #() --array of driver objects which are custom attributes
|
|
maskDriverSpnNameArray = #() --array of names of custom attributes
|
|
maskDriverSpnScalarNameArray = #() --array of scalar names for custom attributes
|
|
maskDriverJSObjArray = #() -- array of joysticks used as drivers
|
|
maskDriverJSTransformArray = #() --array of transform used from joysticks
|
|
maskDriverJSScalarNameArray = #() --array of scalar names from joysticks
|
|
|
|
dataElement = dataElems.itemof(i)
|
|
debugPrint ("i = "+(i as string))
|
|
|
|
debugPrint ("dataElementName = "+(dataElement.name))
|
|
|
|
if dataElement.name == "mask" do
|
|
(
|
|
elementAttrs = dataElement.attributes
|
|
debugPrint ("Found "+(elementAttrs.count as string)+" attributes")
|
|
|
|
for ea = 0 to (elementAttrs.count - 1 ) do
|
|
(
|
|
currentElem = elementAttrs.itemOf(ea)
|
|
|
|
--now we can test for the values
|
|
if (currentElem.Name as string) == "maskExpString" do
|
|
(
|
|
maskExpString = (currentElem.value as string)
|
|
append maskExpStringArray maskExpString
|
|
)
|
|
if (currentElem.Name as string) == "maskName" do
|
|
(
|
|
maskName= (currentElem.value as string)
|
|
append maskNameArray maskName
|
|
)
|
|
if (currentElem.Name as string) == "maskSlider" do
|
|
(
|
|
maskSlider = (currentElem.value as string)
|
|
append maskSliderArray maskSlider
|
|
)
|
|
)
|
|
|
|
--now we look at the children
|
|
dataElemChildren = dataElement.childNodes
|
|
|
|
for c = 0 to (dataElemChildren.count - 1) do
|
|
(
|
|
--ok we're now looking at the driven for this node
|
|
childElement = dataElemChildren.itemOf[c]
|
|
childAttrs = childElement.attributes
|
|
|
|
for cA = 0 to (childAttrs.count - 1) do
|
|
(
|
|
currentChildElem = childAttrs.itemOf(cA)
|
|
|
|
if currentChildElem.name == "maskDriverJSObj" do
|
|
(
|
|
append maskDriverJSObjArray currentChildElem.value
|
|
)
|
|
if currentChildElem.name == "maskDriverJSTransform" do
|
|
(
|
|
append maskDriverJSTransformArray currentChildElem.value
|
|
)
|
|
if currentChildElem.name == "maskDriverJSScalarName" do
|
|
(
|
|
append maskDriverJSScalarNameArray currentChildElem.value
|
|
)
|
|
|
|
if currentChildElem.name == "maskDriverSpnObj" do
|
|
(
|
|
append maskDriverSpnObjArray currentChildElem.value
|
|
)
|
|
if currentChildElem.name == "maskDriverSpnName" do
|
|
(
|
|
append maskDriverSpnNameArray currentChildElem.value
|
|
)
|
|
if currentChildElem.name == "maskDriverSpnScalarName" do
|
|
(
|
|
append maskDriverSpnScalarNameArray currentChildElem.value
|
|
)
|
|
)
|
|
)
|
|
|
|
--now we need to build the joysticks
|
|
|
|
--first off we need to make the joystick parent text so we can move them all around at once....
|
|
textParent = undefined
|
|
textParent = getNodeByName "TEXT_Normals"
|
|
if textParent == undefined do
|
|
(
|
|
textParent = text size:0.1 kerning:0 leading:0 pos:[0.81,-0.0,0.105736] isSelected:on
|
|
textParent.name = "TEXT_Normals"
|
|
textParent.text = "Normals"
|
|
in coordsys world textParent.rotation = (quat 0.707107 0 0 0.707107)
|
|
|
|
textParent.render_displayRenderMesh = true
|
|
textParent.thickness = 0.0025
|
|
textParent.sides = 3
|
|
|
|
max modify mode
|
|
modPanel.addModToSelection (Edit_Poly ()) ui:on
|
|
collapsestack textParent
|
|
)
|
|
|
|
jCount = jCount+1
|
|
|
|
divider = 2.3
|
|
|
|
if jCount < 5 then --1 to 4
|
|
(
|
|
jp = (0+((jCount as float)/ divider ))
|
|
jHeight = -0.0
|
|
)
|
|
else
|
|
(
|
|
if JCount < 9 then -- 5 to 8
|
|
(
|
|
jp = (0+(((jCount as float)- 4) / divider ))
|
|
jHeight = -0.15
|
|
)
|
|
else
|
|
(
|
|
if JCount < 13 then --9 to 12
|
|
(
|
|
jp = (0+(((jCount as float)- 8) / divider ))
|
|
jHeight = -0.3
|
|
)
|
|
else
|
|
(
|
|
if JCount <17 then --13 to 16
|
|
(
|
|
jp = (0+(((jCount as float)- 12) / divider ))
|
|
jHeight = -0.60
|
|
)
|
|
else
|
|
(
|
|
if JCount <21 then --17 to 20
|
|
(
|
|
jp = (0+(((jCount as float) - 16) / divider ))
|
|
jHeight = -0.75
|
|
)
|
|
else
|
|
(
|
|
jp = (0+(((jCount as float) - 20) / divider ))
|
|
jHeight = -0.9
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
jPos = [(0.5 +( jp / 3.5)),-0.5,jHeight]
|
|
jsName = maskSliderArray[1]
|
|
debugprint ("jsName: "+jsName)
|
|
createNormalsJoystick jsname jpos
|
|
|
|
thisJS = getNodeByName jsName
|
|
setUserPropBuffer thisJS "translateTrackType = TRACK_ANIMATED_NORMAL_MAPS"
|
|
|
|
thisJsPar = thisJS.parent
|
|
|
|
thisJSPar.parent = textParent
|
|
|
|
in coordsys parent thisJSPar.position.controller.z_position = 0.0
|
|
|
|
expObj = ("'"+maskSliderArray[1]+"'")
|
|
expCont = (".position.controller[2].Y_Position.controller")
|
|
|
|
scalarObjects = #()
|
|
scalarNames = #()
|
|
scalarConts = #()
|
|
|
|
--now we need to first setup the expressions from joysticks
|
|
--we need to create the paths for the driver controllers ( be they joysticks or cAtts)
|
|
theseConts = #()
|
|
for c = 1 to maskDriverJSObjArray.count do
|
|
(
|
|
thisTrans = (substring maskDriverJSTransformArray[c] 3 60)
|
|
thisContObjStr = ("$"+maskDriverJSObjArray[c]+"."+thisTrans+".controller[2]."+maskDriverJSTransformArray[c]+".controller")
|
|
|
|
append scalarObjects maskDriverJSObjArray[c]
|
|
append scalarConts thisContObjStr
|
|
append scalarNames maskDriverJSScalarNameArray[c]
|
|
)
|
|
|
|
for c = 1 to maskDriverSpnScalarNameArray.count do
|
|
(
|
|
tmpScalarCont = ("$"+maskDriverSpnObjArray[c]+".modifiers[#Attribute_Holder]."+maskDriverSpnObjArray[c]+"_A"+"."+maskDriverSpnNameArray[c]+"_CA.controller")
|
|
append scalarObjects maskDriverSpnObjArray[c]
|
|
append scalarConts tmpScalarCont
|
|
append scalarNames maskDriverSpnScalarNameArray[c]
|
|
)
|
|
|
|
expString = maskExpStringArray[1]
|
|
|
|
--before we add the expression we need to change the expCont into a float Expression
|
|
|
|
execStr = ("$"+expObj+expCont+" = Float_Expression()")
|
|
execute execStr
|
|
generateExpressionIM expObj expCont scalarObjects scalarNames scalarConts expString
|
|
)
|
|
)
|
|
|
|
if ((progBar != undefined) and (progBar.isDisplayed)) do
|
|
(destroyDialog progBar)
|
|
|
|
--now position and scale the parent of all the normal joysticks
|
|
rootObject = getNodeByName "TEXT_Normals"
|
|
in coordsys world rootObject.position = [0.45,0,1.6]
|
|
in coordsys world rootObject.scale = [0.25,0.25,0.25]
|
|
hide rootObject
|
|
)
|
|
else
|
|
(
|
|
messagebox "Please select a valid xml file." Beep:true
|
|
)
|
|
)
|
|
|
|
|
|
--function for running when doing a full prep creation
|
|
fn prepHeadForMashup =
|
|
(
|
|
masterScene = (maxFilePath + maxFileName)
|
|
|
|
hideByCategory.none
|
|
|
|
--save skinning info on all skinned objects
|
|
for o in objects do
|
|
(
|
|
if o.modifiers[#Skin] != undefined do
|
|
(
|
|
saveSkinData o
|
|
)
|
|
)
|
|
|
|
--we need to add a prefix onto the original dupJoints
|
|
for o = 1 to dupJoints.count do
|
|
(
|
|
myJnt = getNodeByName dupJoints[o]
|
|
if myJnt != undefined do
|
|
(
|
|
myJnt.name = ("ORIG_"+myJnt.name)
|
|
)
|
|
)
|
|
|
|
prepSceneForMashup()
|
|
|
|
hideByCategory.none
|
|
currentObjects = objects as array
|
|
|
|
for i = 1 to geoNames[2].count do
|
|
(
|
|
geo = getNodeByNameWildcard geoNames[2][i]
|
|
if geo == undefined do
|
|
(
|
|
messagebox ("warning! couldnt find a node called "+geoNames[2][i])
|
|
--print ("warning! couldnt find a node called "+geoNames[2][i])
|
|
)
|
|
saveSkinData geo
|
|
)
|
|
|
|
for i = 1 to dupJoints.count do --give the 3Lateral joints a prefix
|
|
(
|
|
thisJoint = getNodeByName dupJoints[i]
|
|
thisJoint.name = ("3L_"+thisJoint.name)
|
|
)
|
|
|
|
hideByCategory.none
|
|
|
|
for i = 1 to geoNames[2].count do --now parent the geo to the geo dummy
|
|
(
|
|
max unhide all
|
|
max unfreeze all
|
|
geo = getNodeByName "uppr_000_u"
|
|
if geo == undefined do (geo = getNodeByNameWildcard "uppr_000")
|
|
geoPar = geo.parent
|
|
geo = getNodeByNameWildcard geoNames[2][i]
|
|
geo.parent = geoPar
|
|
)
|
|
|
|
--now we can delete the 3L joints
|
|
for i = 1 to dupJoints.count do
|
|
(
|
|
thisJoint = getNodeByName ("3L_"+dupJoints[i])
|
|
debugPrint ("Deleting 3Later Joint: "+("3L_"+dupJoints[i]))
|
|
delete thisJoint
|
|
)
|
|
|
|
for i = 1 to dupJoints.count do --name the original joints back
|
|
(
|
|
thisJoint = getNodeByName ("ORIG_"+dupJoints[i])
|
|
if thisJoint != undefined do
|
|
(
|
|
thisJoint.name = dupJoints[i]
|
|
)
|
|
)
|
|
|
|
--now parent the facialRoot node to the head
|
|
facialRootNode = getNodeByName "FACIAL_facialRoot"
|
|
facialRootParent = getNodeByName "SKEL_Head"
|
|
facialRootNode.parent = facialRootParent
|
|
|
|
skelJoints = #()
|
|
for o in objects do
|
|
(
|
|
if (substring o.name 1 4) == "SKEL" do
|
|
(
|
|
appendIfUnique skelJoints o
|
|
)
|
|
)
|
|
|
|
--re-create the skin modifiers
|
|
for i = 1 to geoNames[2].count do
|
|
(
|
|
geo = getNodeByNameWildcard geoNames[2][i]
|
|
|
|
if geo.modifiers[#Skin] != undefined do
|
|
(
|
|
select geo
|
|
|
|
execStr = ("collapseStack $"+geo.name)
|
|
execute execStr
|
|
)
|
|
|
|
loadSkinData geo
|
|
)
|
|
|
|
newObjects = objects as array
|
|
nodesToAdd = #()
|
|
|
|
for nO = 1 to newObjects.count do
|
|
(
|
|
if (substring newObjects[nO].name 1 6) == "FACIAL" do
|
|
(
|
|
append nodesToAdd newObjects[nO]
|
|
)
|
|
)
|
|
|
|
selectionSetName = "*EXPRESSIONS"
|
|
addBonesToExpressionSet selectionSetName nodesToAdd
|
|
|
|
parseXml()
|
|
|
|
newObjects = nodesToAdd
|
|
addTags()
|
|
|
|
for i = 1 to geoNames[2].count do
|
|
(
|
|
head = getNodeByNameWildcard geoNames[2][i]
|
|
if head != undefined do
|
|
(
|
|
head.modifiers[#Skin].always_deform = false
|
|
head.modifiers[#Skin].always_deform = true
|
|
)
|
|
)
|
|
|
|
--we now need to assign shaders to teef and tongue
|
|
matToUse = undefined
|
|
|
|
if shaderType == "Player" then
|
|
(
|
|
for i = 1 to 24 do
|
|
(
|
|
head = getNodeByNameWildcard geoNames[2][1]
|
|
teef = getNodeByNameWildcard geoNames[2][2]
|
|
|
|
if meditMaterials[i].name == "Head_RAGE" do
|
|
(
|
|
thisShader = meditMaterials[i].materialList[1]
|
|
matToUse = meditMaterials[i]
|
|
head.material = matToUse
|
|
debugprint "Updating head shader"
|
|
|
|
-- And set it to the correct default shader for characters
|
|
shadertoset = "ped_wrinkle_cs.sps"
|
|
|
|
RstSetShaderName thisShader shadertoset
|
|
|
|
--now need to find the wrinkleMap folder
|
|
if wrinkleFolder != undefined do
|
|
(
|
|
debugprint ("wrinkleFolder = "+wrinkleFolder)
|
|
--now we strip the wrinkleFolder path to prior to the texture name so we have the folder
|
|
pathLength = wrinkleFolder.count
|
|
imageLength = pathlength - 18
|
|
wrinklePath = (substring wrinkleFolder 1 imageLength)
|
|
debugprint ("Folder = "+wrinklePath)
|
|
|
|
wrinkleMasks = #(
|
|
#(
|
|
(wrinklePath+"HEAD_Wrinkle_Mask_0.tga"),
|
|
(wrinklePath+"HEAD_Wrinkle_Mask_1.tga"),
|
|
(wrinklePath+"HEAD_Wrinkle_Mask_2.tga"),
|
|
(wrinklePath+"HEAD_Wrinkle_Mask_3.tga"),
|
|
(wrinklePath+"HEAD_Wrinkle_Mask_4.tga"),
|
|
(wrinklePath+"HEAD_Wrinkle_Mask_5.tga"),
|
|
(wrinklePath+"HEAD_Wrinkle_A.tga"),
|
|
(wrinklePath+"HEAD_Wrinkle_B.tga")
|
|
),
|
|
#(
|
|
"Wrinkle Mask 0",
|
|
"Wrinkle Mask 1",
|
|
"Wrinkle Mask 2",
|
|
"Wrinkle Mask 3",
|
|
"Wrinkle Mask 4",
|
|
"Wrinkle Mask 5",
|
|
"Wrinkle A",
|
|
"Wrinkle B"
|
|
)
|
|
)
|
|
|
|
--NOW WE NEED TO COPY THE WRINKLES TO THE CHARACTERS TEXTURES\HIGHRES\ FOLDER
|
|
|
|
moveWrinkleMap wrinklePath wrinkleMasks
|
|
|
|
shdrParams = RstGetVariableCount thisShader
|
|
|
|
if shdrParams != undefined do
|
|
(
|
|
-- for sParam = 1 to shdrParams.count do
|
|
for sParam = 1 to shdrParams do
|
|
(
|
|
thisParam = RstGetVariableName thisShader sParam
|
|
for wm = 1 to wrinkleMasks[2].count do
|
|
(
|
|
if thisParam == wrinkleMasks[2][wm] do
|
|
(
|
|
print ("wrinkleMasks[1]["+(wm as string)+"]: "+(wrinkleMasks[1][wm] as string))
|
|
|
|
--now we need to set this parameter to be wrinkleMasks[1][wm]
|
|
RstSetVariable thisShader sParam wrinkleMasks[1][wm]
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
if meditMaterials[i].name == "Hair 2_RAGE" do
|
|
(
|
|
matToUse = meditMaterials[i]
|
|
teef.material = matToUse
|
|
debugprint ("updating TEEF shader")
|
|
)
|
|
)
|
|
)
|
|
else
|
|
(
|
|
head = getNodeByNameWildcard geoNames[2][1]
|
|
if head == undefined do
|
|
(
|
|
thisGeoName = undefined
|
|
if (substring geoNames[2][1] 1 1 ) == "H" do
|
|
(
|
|
thisGeoName = ("h"+(substring geoNames[2][1] 2 60 ) )
|
|
)
|
|
head = getNodeByNameWildcard thisGeoName
|
|
)
|
|
|
|
teef = getNodeByNameWildcard geoNames[2][2]
|
|
if teef == undefined do
|
|
(
|
|
thisGeoName = undefined
|
|
if (substring geoNames[2][1] 1 1 ) == "T" do
|
|
(
|
|
thisGeoName = ("t"+(substring geoNames[2][1] 2 60 ) )
|
|
)
|
|
teef = getNodeByNameWildcard thisGeoName
|
|
)
|
|
|
|
thisShader = meditMaterials[13].materialList[1]
|
|
matToUse = meditMaterials[13]
|
|
head.material = matToUse
|
|
debugprint "Updating head shader"
|
|
|
|
-- And set it to the correct default shader for characters
|
|
shadertoset = "ped_wrinkle_cs.sps"
|
|
|
|
RstSetShaderName thisShader shadertoset
|
|
|
|
--now need to find the wrinkleMap folder
|
|
if wrinkleFolder != undefined do
|
|
(
|
|
debugprint ("wrinkleFolder = "+wrinkleFolder)
|
|
--now we strip the wrinkleFolder path to prior to the texture name so we have the folder
|
|
pathLength = wrinkleFolder.count
|
|
imageLength = pathlength - 18
|
|
wrinklePath = (substring wrinkleFolder 1 imageLength)
|
|
debugprint ("Folder = "+wrinklePath)
|
|
|
|
wrinkleMasks = #(
|
|
#(
|
|
(wrinklePath+"HEAD_Wrinkle_Mask_0.tga"),
|
|
(wrinklePath+"HEAD_Wrinkle_Mask_1.tga"),
|
|
(wrinklePath+"HEAD_Wrinkle_Mask_2.tga"),
|
|
(wrinklePath+"HEAD_Wrinkle_Mask_3.tga"),
|
|
(wrinklePath+"HEAD_Wrinkle_Mask_4.tga"),
|
|
(wrinklePath+"HEAD_Wrinkle_Mask_5.tga"),
|
|
(wrinklePath+"HEAD_Wrinkle_A.tga"),
|
|
(wrinklePath+"HEAD_Wrinkle_B.tga")
|
|
),
|
|
#(
|
|
"Wrinkle Mask 0",
|
|
"Wrinkle Mask 1",
|
|
"Wrinkle Mask 2",
|
|
"Wrinkle Mask 3",
|
|
"Wrinkle Mask 4",
|
|
"Wrinkle Mask 5",
|
|
"Wrinkle A",
|
|
"Wrinkle B"
|
|
)
|
|
)
|
|
|
|
moveWrinkleMap wrinklePath wrinkleMasks
|
|
|
|
shdrParams = RstGetVariableCount thisShader
|
|
|
|
for sParam = 1 to shdrParams do
|
|
(
|
|
thisParam = RstGetVariableName thisShader sParam
|
|
for wm = 1 to wrinkleMasks[2].count do
|
|
(
|
|
if thisParam == wrinkleMasks[2][wm] do
|
|
(
|
|
print ("wrinkleMasks[1]["+(wm as string)+"]: "+(wrinkleMasks[1][wm] as string))
|
|
--now we need to set this parameter to be wrinkleMasks[1][wm]
|
|
RstSetVariable thisShader sParam wrinkleMasks[1][wm]
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
if foundPLayerShader ==true then
|
|
(
|
|
matToUse = meditMaterials[16]
|
|
)
|
|
else
|
|
(
|
|
matToUse = meditMaterials[13]
|
|
)
|
|
debugprint ("Original teef material = "+(teef.material as string))
|
|
teef.material = matToUse
|
|
debugprint ("Final teef material = "+(teef.material as string))
|
|
|
|
debugprint ("updating TEEF shader")
|
|
)
|
|
--now we setup the normals shit
|
|
parseNormalsXML()
|
|
|
|
-- now we need to ensure any scale controllers on the gui objects have also been concatenated
|
|
for i = 1 to controlGUIObjects.count do
|
|
(
|
|
thisBone = controlGUIObjects[i]
|
|
|
|
spclCaseConCat = false
|
|
|
|
if (classof thisBone.scale.controller as string) == "scale_list" do
|
|
(
|
|
concatThis = true
|
|
for nc = 1 to nonConcatJoints.count do
|
|
(
|
|
if thisBone.name == nonConcatJoints[nc] do
|
|
(
|
|
concatThis = false
|
|
|
|
spclCaseConCat = true
|
|
)
|
|
)
|
|
|
|
if concatThis == true do
|
|
(
|
|
if thisBone.scale.controller.count > 2 do
|
|
(
|
|
--now we need to check all existing controllers and see if they are x y or z so we know if we need to add a correspondig offset
|
|
xCont = false
|
|
yCont = false
|
|
zCont = false
|
|
|
|
for c = 2 to thisBone.scale.controller.count do
|
|
(
|
|
xC = thisBone.scale.controller[c].X_Scale.controller
|
|
yC = thisBone.scale.controller[c].Y_Scale.controller
|
|
zC = thisBone.scale.controller[c].Z_Scale.controller
|
|
|
|
if (xC as string) == "Controller:Float_Expression" do
|
|
(
|
|
xCont = true
|
|
)
|
|
if (yC as string) == "Controller:Float_Expression" do
|
|
(
|
|
yCont = true
|
|
)
|
|
if (zC as string) == "Controller:Float_Expression" do
|
|
(
|
|
zCont = true
|
|
)
|
|
)
|
|
|
|
if xCont == true do
|
|
(
|
|
concatScale thisBone "X_Scale" spclCaseConCat
|
|
)
|
|
if yCont == true do
|
|
(
|
|
concatScale thisBone "Y_Scale" spclCaseConCat
|
|
)
|
|
if zCont == true do
|
|
(
|
|
concatScale thisBone "Z_Scale" spclCaseConCat
|
|
)
|
|
)
|
|
removeOldScaleControllers thisBone
|
|
)
|
|
)
|
|
)
|
|
|
|
--now run the external file to set the joystick limits back
|
|
|
|
filein (RsConfigGetWildWestDir() + "script/3dsMax/Characters/Rigging/3Lateral/addJoyystickLimits.ms")
|
|
|
|
-- Now convert the spline geo joysticks and text to alphad planes for speed in motionbuilder
|
|
convertStandardGuiToAlphaGUI()
|
|
)
|
|
|
|
fn justXml = --this will prep all nodes for the just xml segment
|
|
(
|
|
--first we need to get all joints in the head
|
|
--then we need to freeze all controllers
|
|
|
|
bonesInSkin = #()
|
|
|
|
facialXmlFile = undefined
|
|
|
|
if facialXmlFile == undefined do
|
|
(
|
|
facialXmlFile = getOpenFileName caption:"Facial XML File" types:"XML Data (*joint*.xml)|*joint*.xml|All Files (*.*)|*.*|"
|
|
)
|
|
|
|
headNode = getNodeByName geoNames[2][1]
|
|
if headNode != undefined do
|
|
(
|
|
select headNode
|
|
max modify mode
|
|
modPanel.setCurrentObject $.modifiers[#Skin]
|
|
|
|
if headNode.modifiers[#Skin] != undefined do
|
|
(
|
|
--now we need to get all joints in the skin modifier and add to the bonesInSkin array
|
|
boneIndexes = skinOps.GetNumberBones headNode.modifiers[#Skin]
|
|
for i = 1 to boneIndexes do
|
|
(
|
|
currentBoneName = skinOps.GetBoneName headNode.modifiers[#Skin] i 0
|
|
appendIfUnique bonesInSkin currentBoneName
|
|
)
|
|
|
|
|
|
)
|
|
--now we need to freeze transforms on bonesInSkin nodes
|
|
for i = 1 to bonesInSkin.count do
|
|
(
|
|
fbL = facialBonePrefix.count
|
|
if (substring bonesInSkin[i] 1 fbl) == facialBonePrefix do
|
|
(
|
|
thisNode = getNodeByName bonesInSkin[i]
|
|
select thisNode
|
|
freezeTransform()
|
|
)
|
|
)
|
|
)
|
|
|
|
|
|
parseXml()
|
|
|
|
|
|
for i = 1 to geoNames[2].count do
|
|
(
|
|
--hack
|
|
head = getNodeByName geoNames[2][1]
|
|
--end hack
|
|
|
|
if head != undefined do
|
|
(
|
|
head.modifiers[#Skin].always_deform = false
|
|
head.modifiers[#Skin].always_deform = true
|
|
)
|
|
)
|
|
|
|
-- messagebox "Done!" Beep:true
|
|
print "Done!"
|
|
)
|
|
|
|
fn queryMat = --function which queries shader names to see if shaders in scene are old school or new PLAYER style
|
|
(
|
|
for i = 1 to 24 do
|
|
(
|
|
if meditMaterials[i].name == "Upper_RAGE" do
|
|
(
|
|
foundPLayerShader = true
|
|
)
|
|
)
|
|
)
|
|
|
|
-- A function here will prebake all selected model parts to a default gray
|
|
fn vertPrebake =
|
|
(
|
|
setCommandPanelTaskMode #modify
|
|
|
|
selectMeshes2Bake = #()
|
|
|
|
for meshes2Bake=1 to geoNames[2].count do
|
|
(
|
|
selectByWildcard geoNames[2][meshes2Bake]
|
|
tempSelection = getCurrentSelection()
|
|
appendIfUnique selectMeshes2Bake tempSelection[1]
|
|
)
|
|
|
|
for i = 1 to selectMeshes2Bake.count do
|
|
(
|
|
obj = selectMeshes2Bake[i]
|
|
|
|
-- Turn on the Vertex colours, set to channel 0
|
|
obj.showVertexColors = on
|
|
obj.vertexColorType = 0
|
|
|
|
try-- For each object in turn, go to the base mesh
|
|
(
|
|
modPanel.setCurrentObject obj.baseObject
|
|
subobjectLevel = 1 -- Go to vertex mode
|
|
nv=0 -- get number of verts in the object
|
|
|
|
if classof obj == Editable_Poly then
|
|
(
|
|
nv = obj.numverts
|
|
|
|
if ((progBar != undefined) and (progBar.isDisplayed)) do
|
|
(destroyDialog progBar)
|
|
|
|
createDialog progBar width:400 Height:30
|
|
|
|
|
|
for i = 1 to nv do
|
|
(
|
|
polyop.setvertcolor $ TheColourChannel i Ped_BakeColour
|
|
polyop.setvertcolor $ TheRimChannel i Ped_RimColour
|
|
polyop.setvertcolor $ TheWindChannel i Ped_WindColour
|
|
polyop.setvertcolor $ TheEnvEffChannel i Ped_EnvEffColour
|
|
polyop.setvertcolor $ TheAlphaChannel i Ped_AlphaColour
|
|
|
|
a = (nv / 100)
|
|
progBar.prog.value = (1.*i/a)
|
|
)
|
|
)
|
|
|
|
if classof obj == Editable_Mesh then
|
|
(
|
|
nv = obj.numverts
|
|
|
|
if ((progBar != undefined) and (progBar.isDisplayed)) do
|
|
(destroyDialog progBar)
|
|
|
|
createDialog progBar width:400 Height:30
|
|
|
|
for i = 1 to nv do
|
|
(
|
|
meshop.setvertcolor $ TheColourChannel i Ped_BakeColour
|
|
meshop.setvertcolor $ TheRimChannel i Ped_RimColour
|
|
meshop.setvertcolor $ TheWindChannel i Ped_WindColour
|
|
meshop.setvertcolor $ TheEnvEffChannel i Ped_EnvEffColour
|
|
meshop.setvertcolor $ TheAlphaChannel i Ped_AlphaColour
|
|
|
|
a = (nv / 100)
|
|
progBar.prog.value = (1.*i/a)
|
|
)
|
|
)
|
|
|
|
if ((progBar != undefined) and (progBar.isDisplayed)) do
|
|
(destroyDialog progBar)
|
|
|
|
subobjectLevel = 0
|
|
)catch (print"Couldn't get to object base Epoly/EMesh")
|
|
) -- object selection loop
|
|
clearSelection()
|
|
) -- End vertPrebake
|
|
|
|
--a function to set "Weld Without Quantise" attribute on head and teef meshes
|
|
fn weldAttributes =
|
|
(
|
|
for meshes2Quantise = 1 to geoNames[2].count do
|
|
(
|
|
thisMesh = getNodeByNameWildcard geoNames[2][meshes2Quantise]
|
|
|
|
if thisMesh != undefined do
|
|
(
|
|
setAttribute thisMesh "Weld Without Quantise" true
|
|
)
|
|
)
|
|
)--end weldAttributes
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
if ((highEndFacialSetupGUI != undefined) and (highEndFacialSetupGUI.isDisplayed)) do
|
|
(destroyDialog highEndFacialSetupGUI)
|
|
|
|
rollout highEndFacialSetupGUI "Highclass Facial"
|
|
(
|
|
checkBox chkDebugPrnt "DebugPrint" checked:false tooltip:"Check to enable debug --print output."
|
|
checkBox chkPsdhead "PSD" checked:false tooltip:"Enable if this is a Pose Space Deformer head."
|
|
spinner spn_vtxWeight "Influences" default:4 tooltip:"Number of weights per vertex" type:#integer
|
|
|
|
button btnPrepFull "Head & Body" width:110 tooltip:"Add head to a scene with a body."
|
|
|
|
button btnReconnectNormals "Re Wrinkle Map" width:110 tooltip:"Reconnect animated normal textures and shader"
|
|
|
|
on highEndFacialSetupGUI open do
|
|
(
|
|
chkDebugPrnt.state = false
|
|
debugPrintVal = false
|
|
spn_vtxWeight.value = 4
|
|
chkPsdheadVal = false
|
|
)
|
|
|
|
on chkDebugPrnt changed theState do
|
|
(
|
|
if chkDebugPrnt.state == false then
|
|
(
|
|
debugPrintVal = false
|
|
)
|
|
else
|
|
(
|
|
debugPrintVal = true
|
|
)
|
|
)
|
|
|
|
on chkPsdhead changed theState do
|
|
(
|
|
if chkPsdhead.state == false then
|
|
(
|
|
chkPsdheadVal = false
|
|
)
|
|
else
|
|
(
|
|
chkPsdheadVal = true
|
|
)
|
|
)
|
|
|
|
on btnPrepFull pressed do
|
|
(
|
|
while contin == true do --had to add a while as sometimes the script wouldnt exit correctly.
|
|
(
|
|
vtxWeight = spn_vtxWeight.value
|
|
|
|
startFr = timestamp()
|
|
|
|
deactivateHeels() --reset any heel joystick shit
|
|
--first off ensure we delete any existing facial_ nodes
|
|
iwannaDelete = #()
|
|
for o in objects do
|
|
(
|
|
if (substring o.name 1 7) == "FACIAL_" do
|
|
(
|
|
append iwannadelete o
|
|
)
|
|
)
|
|
|
|
delete iwannaDelete
|
|
|
|
upprGeo = getNodeByNameWildcard "uppr_000"
|
|
if upprGeo != undefined then
|
|
(
|
|
--first find what type of shaderType this character is
|
|
|
|
queryMat()
|
|
|
|
--need to query scene and if we find a shader called upper and lower then its player style and if its got Rage001 then its old school. If none then query
|
|
|
|
-- if queryBox "Click Yes if this is a player shader file or No for old style." beep:true then
|
|
if foundPLayerShader == true then
|
|
(
|
|
shaderType = "Player"
|
|
)
|
|
else
|
|
(
|
|
shaderType = "OldSchool"
|
|
)
|
|
|
|
facialXmlFile = undefined
|
|
facialXmlFile = getOpenFileName caption:"Facial XML File" types:"XML Data (*joint*.xml)|*joint*.xml|All Files (*.*)|*.*|"
|
|
facialFbxFile = getOpenFileName caption:"FBX Facial File" types:"FBX Data (*.FBX)|*.fbx|All Files (*.*)|*.*|"
|
|
facialGUIFile = getOpenFileName caption:"Max GUI File" types:"Max Data (*.Max)|*.max|All Files (*.*)|*.*|"
|
|
|
|
normalsXmlFile = getOpenFileName caption:"Normals XML File" types:"XML Data (*slider*.xml)|*slider*.xml|All Files (*.*)|*.*|"
|
|
wrinkleFolder = getOpenFileName caption:"Wrinkle Folder " types:"Tga files (HEAD_Wrinkle_A.tga)|HEAD_Wrinkle_A.tga|All Files (*.*)|*.*|"
|
|
prepHeadForMashup()
|
|
vertPrebake()
|
|
weldAttributes()
|
|
|
|
print ("Facial Hookup Complete.")
|
|
-- messagebox "Done!" Beep:true
|
|
)
|
|
else
|
|
(
|
|
messagebox ("Please ensure you have a character scene open to mash head onto.") beep:true
|
|
)
|
|
|
|
gc()
|
|
|
|
end = timeStamp()
|
|
format "Processing 3Lateral Hookup took % seconds\n" ((end - startFr) / 1000.0)
|
|
format "Processing 3Lateral Hookup took % minutes\n" (((end - startFr) / 1000.0) / 60)
|
|
|
|
--break()
|
|
testSync = true
|
|
|
|
toolFileName = getThisScriptFilename()
|
|
|
|
--messagebox (toolFileName as string)
|
|
|
|
versionNumber = getToolRevision toolFileName
|
|
|
|
|
|
versionTag = ("Generated with tool revision: "+(versionNumber as string)+"\n")
|
|
|
|
faceUI = getNodeByName "faceControls_FRAME"
|
|
|
|
setUserPropBuffer FaceUI versionTag
|
|
|
|
contin = false
|
|
|
|
if contin == false do exit --another attempt to hack an exit upon completion - some large files print the completion message thern hang using 100% system resources
|
|
)
|
|
)
|
|
|
|
on btnReconnectNormals pressed do
|
|
(
|
|
filein (RsConfigGetWildWestDir() + "script/3dsMax/Characters/Rigging/3Lateral/reconnectWrinkleMaps.ms")
|
|
)
|
|
|
|
)
|
|
|
|
|
|
CreateDialog highEndFacialSetupGUI width:125 pos:[1450, 100]
|