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]