513 lines
16 KiB
Plaintext
Executable File
513 lines
16 KiB
Plaintext
Executable File
--tool for pre skin data transfer setup to bring in a template mesh
|
|
|
|
--we will bring in the template mesh
|
|
|
|
--rename the receiver meshes joints to match a predefined template name
|
|
|
|
--load skinning for template mesh via load enevelopes
|
|
|
|
--rename joints back to origninal names
|
|
|
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
filein "rockstar/export/settings.ms" -- This is fast
|
|
|
|
-- Figure out the project
|
|
global theProjectRoot = RsConfigGetProjRootDir()
|
|
global theProject = RSConfigGetProjectName()
|
|
global theWildWest = RsConfigGetWildWestDir()
|
|
global theProjectConfig = RsConfigGetProjBinConfigDir()
|
|
|
|
global toolsRoot = RsConfigGetToolsRootDir()
|
|
|
|
global boneList = #()
|
|
|
|
global mjrTarget = undefined
|
|
|
|
global handVerts = #() --used for storing which verts comprise the hands for if we want to preserve hand skinning
|
|
global skinDataFileName = "c:/skins/skinDataTransferHands.skn"
|
|
-- filein (theProjectRoot + "tools/wildwest/script/3dsMax/Characters/Rigging/usefulScripts/Skinning_Tools.ms")
|
|
filein (toolsRoot + "/wildwest/script/3dsMax/_common_functions/FN_Rigging.ms")
|
|
|
|
global RsPreserveHandSkin = true
|
|
global skinXFerComplete = undefined
|
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
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 inputHandSkinData recMesh =
|
|
(
|
|
-- loadedSkinData = ST_input_skin_data recMesh skinDataFileName
|
|
|
|
format ("Loading "+skinDataFileName+" onto "+(recMesh as string)+"\n")
|
|
ST_apply_skin_weights recMesh skinDataFileName
|
|
)
|
|
|
|
fn outPutHandSkinData recMesh =
|
|
(
|
|
--this will use a vol select to select verts that make the hands and save out their skinning data for later loading
|
|
--we will do this by doing a vol select around each middle finger 20 joint
|
|
|
|
local skinMod = recMesh.modifiers[#Skin]
|
|
|
|
-- Abort if model has no Skin modifier:
|
|
if (skinMod == undefined) do
|
|
(
|
|
RsPreserveHandSkin = false
|
|
return False
|
|
)
|
|
|
|
--now we'll make a selectionVolume
|
|
volSphere = Sphere radius:0.2 smooth:on segs:32 chop:0 slice:off sliceFrom:0 sliceTo:0 mapcoords:on recenter:off pos:[0,0,0] isSelected:on name:"VolSphere" color:green
|
|
|
|
SetCommandPanelTaskMode #Modify
|
|
|
|
--first we'll gather the right hand verts
|
|
|
|
volSphere.transform = $SKEL_R_Finger20.transform
|
|
modPanel.setCurrentObject recMesh.baseObject
|
|
local volSelMod = Vol__Select()
|
|
modPanel.addModToSelection volSelMod ui:on
|
|
volSelMod.level = 1
|
|
volSelMod.volume = 3
|
|
volSelMod.node = VolSphere
|
|
|
|
selectedVerts = recMesh.mesh.selectedVerts as bitarray
|
|
|
|
for vert in selectedVerts do
|
|
(
|
|
append handVerts vert
|
|
)
|
|
|
|
--now do the other hand
|
|
|
|
volSphere.transform = $SKEL_L_Finger20.transform
|
|
selectedVerts = recMesh.mesh.selectedVerts as bitarray
|
|
|
|
for vert in selectedVerts do
|
|
(
|
|
append handVerts vert
|
|
)
|
|
|
|
if handVerts.count < 1 do
|
|
(
|
|
format ("Warning! "+recMesh.name+" mesh doesnt appear to HAVE any hands!")
|
|
RsPreserveHandSkin = false
|
|
)
|
|
|
|
--now we can delete the volSelect modifier etc
|
|
delete volSphere
|
|
for modi = recMesh.modifiers.count to 1 by -1 do
|
|
(
|
|
if recMesh.modifiers[modi].name == "Vol. Select" do
|
|
(
|
|
deleteModifier recMesh modi
|
|
)
|
|
)
|
|
|
|
|
|
--now we're ready to save the data out
|
|
modPanel.setCurrentObject skinMod
|
|
skinOps.SelectVertices skinMod handVerts
|
|
|
|
skinnedVertListData = ST_get_skin_weights recMesh --first of all query the skin weights
|
|
|
|
ST_output_skin_data theMeshObject skinnedVertListData skinDataFileName
|
|
)
|
|
|
|
fn inputBones input_name =
|
|
(
|
|
--*************************************************************************************
|
|
-- NEED TO ADD A DISABLE UI HERE OTHERWISE IT TAKES AGES!
|
|
--*************************************************************************************
|
|
|
|
Geo = selection
|
|
if Geo.count == 1 then
|
|
(
|
|
|
|
g = $
|
|
if g.modifiers[#Skin] == undefined then
|
|
(
|
|
messageBox "Please pick an object with a skin modifier." title:"gta5_boneinput"
|
|
)
|
|
else
|
|
(
|
|
skinMod = $.modifiers[#Skin]
|
|
if input_name == undefined do
|
|
(
|
|
input_name = getOpenFileName caption:"Bone input file" types:"BoneData (*.bon)|*.bon|All Files (*.*)|*.*|"
|
|
)
|
|
|
|
if input_name != undefined then
|
|
(
|
|
f = openfile input_name
|
|
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)))
|
|
currBone = (substring currBonename 4 (currBonelength - 5))
|
|
-- executeStr = ("if "+currBone+" != undefined do ("+"select "+currBone+")")
|
|
-- currentBone = execute executeStr
|
|
-- currentBone = execute currBone
|
|
|
|
currentBone = getNodeByName currBone
|
|
-- if currentBone != undefined do
|
|
if currentBone != undefined then
|
|
(
|
|
appendIfUnique boneList currentBone
|
|
)
|
|
else
|
|
(
|
|
print ("Couldn't find "+currBone+" in this scene.")
|
|
)
|
|
)
|
|
-- print ("BoneList = " +(boneList as String))
|
|
|
|
select g
|
|
SetCommandPanelTaskMode mode:#modify
|
|
|
|
for i = 1 to boneList.count do
|
|
(
|
|
|
|
boneToAdd = getNodeByName bonelist[i].name
|
|
|
|
boneUpdateInt = undefined
|
|
if i != bonelist.count then
|
|
(
|
|
boneUpdateInt = 1
|
|
)
|
|
else
|
|
(
|
|
boneUpdateInt = 0
|
|
)
|
|
|
|
if boneToAdd != undefined do
|
|
(
|
|
skinOps.addbone g.modifiers[#Skin] boneList[i] boneUpdateInt
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
)
|
|
else
|
|
(
|
|
messageBox "Please run with only 1 object selected." title:"gta5_boneinput"
|
|
)
|
|
)
|
|
|
|
fn importTemplateMesh recMesh templateString =
|
|
(
|
|
--this will merge in a predefined head which has skinning onto a rig with joints with a TEMPLATE suffix instead of a name.
|
|
--we merge in the head then rename the joints suffix of the existing recMesh to have a TEMPLATE suffix instead of their number
|
|
--we then load the skinning form a predefined bone and weight file for the template mesh
|
|
--then rename the joints back to the number of the recMesh
|
|
|
|
--turn off the gta callbacks
|
|
callbacks.removeScripts id:#RsGlobalCallbacks
|
|
|
|
--Facial Rig template
|
|
-- templateMeshFile = (theProjectRoot + "art/peds/AmbientHead/templateHead.max")
|
|
-- templateSkinFile = (theProjectRoot + "art/peds/AmbientHead/templateMesh.env")
|
|
-- templateBoneFile = (theProjectRoot + "art/peds/AmbientHead/templateMesh.bon")#
|
|
tPr = "x:/gta5/"
|
|
templateMeshFile = (tPr + "art/peds/AmbientHead/templateHead.max")
|
|
templateSkinFile = (tPr + "art/peds/AmbientHead/templateMesh.env")
|
|
templateBoneFile = (tPr + "art/peds/AmbientHead/templateMesh.bon")
|
|
|
|
|
|
if( templateString == "B-Rig [Ortega]" ) then
|
|
(
|
|
--Facial B-Rig template [Ortega]
|
|
print "Ortega"
|
|
-- templateMeshFile = (theProjectRoot + "art/peds/AmbientHead/B_Rigs/templateHead_Ortega.max")
|
|
-- templateSkinFile = (theProjectRoot + "art/peds/AmbientHead/B_Rigs/templateMesh_Ortega.env")
|
|
-- templateBoneFile = (theProjectRoot + "art/peds/AmbientHead/B_Rigs/templateMesh_Brig.bon")
|
|
templateMeshFile = (tPr + "art/peds/AmbientHead/B_Rigs/templateHead_Ortega.max")
|
|
templateSkinFile = (tPr + "art/peds/AmbientHead/B_Rigs/templateMesh_Ortega.env")
|
|
templateBoneFile = (tPr + "art/peds/AmbientHead/B_Rigs/templateMesh_Brig.bon")
|
|
)
|
|
|
|
if( templateString == "B-Rig [ProlSec]" ) then
|
|
(
|
|
--Facial B-Rig template [ProlSec]
|
|
print "ProlSec"
|
|
-- templateMeshFile = (theProjectRoot + "art/peds/AmbientHead/B_Rigs/templateHead_B_ProlSec.max")
|
|
-- templateSkinFile = (theProjectRoot + "art/peds/AmbientHead/B_Rigs/templateMesh_B_ProlSec.env")
|
|
-- templateBoneFile = (theProjectRoot + "art/peds/AmbientHead/B_Rigs/templateMesh_Brig.bon")
|
|
templateMeshFile = (tPr + "art/peds/AmbientHead/B_Rigs/templateHead_B_ProlSec.max")
|
|
templateSkinFile = (tPr + "art/peds/AmbientHead/B_Rigs/templateMesh_B_ProlSec.env")
|
|
templateBoneFile = (tPr + "art/peds/AmbientHead/B_Rigs/templateMesh_Brig.bon")
|
|
)
|
|
|
|
foundData = 0 --used to track if files exist
|
|
|
|
if doesFileExist templateMeshFile != true then
|
|
(
|
|
print ("Syncing "+templateMeshFile)
|
|
|
|
-- sync templateMeshFile
|
|
gRsPerforce.sync templateMeshFile silent:true force:true
|
|
|
|
if doesFileExist templateMeshFile != true then
|
|
(
|
|
format ("WARNING FAILED Syncing "+templateMeshFile+"\n")
|
|
messagebox ("WARNING FAILED Syncing "+templateMeshFile+"\n")
|
|
)
|
|
)
|
|
|
|
if doesFileExist templateBoneFile != true then
|
|
(
|
|
print ("Syncing "+templateBoneFile)
|
|
|
|
-- sync templateBoneFile
|
|
gRsPerforce.sync templateBoneFile silent:true force:true
|
|
|
|
if doesFileExist templateBoneFile != true then
|
|
(
|
|
format ("WARNING FAILED Syncing "+templateBoneFile+"\n")
|
|
messagebox ("WARNING FAILED Syncing "+templateBoneFile+"\n")
|
|
)
|
|
)
|
|
|
|
if doesFileExist templateSkinFile != true then
|
|
(
|
|
print ("Syncing "+templateSkinFile)
|
|
|
|
-- sync templateSkinFile
|
|
gRsPerforce.sync templateSkinFile silent:true force:true
|
|
|
|
if doesFileExist templateSkinFile != true then
|
|
(
|
|
format ("WARNING FAILED Syncing "+templateSkinFile+"\n")
|
|
messagebox ("WARNING FAILED Syncing "+templateSkinFile+"\n")
|
|
)
|
|
)
|
|
|
|
if doesFileExist templateMeshFile == true then
|
|
(
|
|
if doesFileExist templateBoneFile == true then
|
|
(
|
|
if doesFileExist templateSkinFile == true then
|
|
(
|
|
|
|
mergeMaxFile templateMeshFile #deleteOldDups #useSceneMtlDups #alwaysReparent quiet:true
|
|
|
|
tempMesh = getNodeByName "templateMesh"
|
|
|
|
boneList = #()
|
|
|
|
currsel = selection as array
|
|
|
|
select tempMesh
|
|
|
|
--now we need to do the bone renaming bit.
|
|
|
|
meshName = recMesh.name
|
|
|
|
tempMesh.pivot = recMesh.pivot
|
|
-- meshLength = meshName.count
|
|
-- meshNo = (substring meshName (meshLength - 3) 3)
|
|
meshNo = filterString meshName "_"
|
|
meshNo = meshNo[2]
|
|
|
|
for o in objects do
|
|
(
|
|
if (classof o as string) == "BoneGeometry" do
|
|
(
|
|
oName = o.name
|
|
if (substring o.name (oName.count - 2) 3) == meshNo do
|
|
(
|
|
format ("renaming "+o.name+"\n")
|
|
o.name = ((substring o.name 1 (oName.count - 3))+"TEMPLATE")
|
|
)
|
|
)
|
|
)
|
|
|
|
modPanel.addModToSelection (Skin ()) ui:on
|
|
tempMesh.modifiers[#Skin].bone_Limit = 4
|
|
|
|
inputBones templateBoneFile
|
|
|
|
DialogMonitorOPS.RegisterNotification LSW_EnvelopeCallbackFunction ID:#ANoon_Envelopes
|
|
DialogMonitorOPS.Enabled = true
|
|
|
|
completeRedraw()
|
|
skinOps.loadEnvelope tempMesh.modifiers[#Skin] templateSkinFile
|
|
|
|
completeRedraw()
|
|
|
|
DialogMonitorOPS.Enabled = false
|
|
DialogMonitorOPS.UnRegisterNotification ID:#ANoon_Envelopes
|
|
|
|
--need to toggle always defmore on the template mesh
|
|
tempMesh.modifiers[#Skin].always_Deform = false
|
|
tempMesh.modifiers[#Skin].always_Deform = true
|
|
|
|
--NOW RENAME THE JOINTS BACK
|
|
for o in objects do
|
|
(
|
|
if (classof o as string) == "BoneGeometry" do
|
|
(
|
|
oName = o.name
|
|
--print ("obj: "+oName)
|
|
-- if (substring o.name (oName.count - 7) 8) == "TEMPLATE" do
|
|
isTemplate = findString o.name "TEMPLATE"
|
|
if isTemplate != undefined do
|
|
(
|
|
format ("renaming "+o.name+"\n")
|
|
o.name = ((substring o.name 1 (oName.count - 8))+meshNo)
|
|
)
|
|
)
|
|
)
|
|
completeRedraw()
|
|
|
|
--turn back on the gta callbacks
|
|
|
|
-- filein (theProjectRoot+ "tools/dcc/current/max2012/scripts/pipeline/util/global_callbacks.ms")
|
|
|
|
filein (toolsRoot+ "/dcc/current/max2012/scripts/pipeline/util/global_callbacks.ms")
|
|
|
|
for o in objects do
|
|
(
|
|
if o != recMesh do
|
|
(
|
|
if o != tempMesh do
|
|
(
|
|
hide o
|
|
)
|
|
)
|
|
)
|
|
)
|
|
else
|
|
(
|
|
format ("Quiting out due to missing "+templateSkinFile+"\n")
|
|
)
|
|
)
|
|
else
|
|
(
|
|
format ("Quiting out due to missing "+templateBoneFile+"\n")
|
|
)
|
|
)
|
|
else
|
|
(
|
|
format ("Quiting out due to missing "+templateMeshFile+"\n")
|
|
)
|
|
)
|
|
|
|
-- recMesh = $Head_001_R
|
|
-- importTemplateMesh recMesh
|
|
|
|
try (destroyDialog RStransferSkinDataUI) catch ()
|
|
rollout RStransferSkinDataUI "Transfer Skin Data" width:170
|
|
(
|
|
dotNetControl rsBannerPanel "Panel" pos:[0,0] height:32 width:RStransferSkinDataUI.width
|
|
local banner = makeRsBanner dn_Panel:rsBannerPanel wiki:"SkinDataXFer_Prep" filename:(getThisScriptFilename())
|
|
|
|
fn sourceFilter obj = (isKindOf obj.baseObject Editable_Poly) and (obj.modifiers[#skin] != undefined)
|
|
fn targetFilter obj = (isKindOf obj.baseObject Editable_Poly)
|
|
|
|
-- pickbutton getSourceObjBtn "[pick Source]" filter:targetFilter autoDisplay:true width:130 across:2
|
|
dropdownlist templateCombo width:145 items:#("B-Rig [Ortega]", "B-Rig [ProlSec]", "Standard Rig")
|
|
pickbutton getTargetObjBtn "[pick Target]" filter:targetFilter autoDisplay:true width:145 color:green
|
|
checkBox keepHandsChk "Preserve Hand Skinning" default:false
|
|
|
|
local objBtns = #(getTargetObjBtn)
|
|
|
|
button skinXferBtn "Launch Skin Transfer" width:145
|
|
|
|
on RStransferSkinDataUI open do
|
|
(
|
|
banner.setup()
|
|
skinXferBtn.enabled = false
|
|
RsPreserveHandSkin = keepHandsChk.state
|
|
|
|
--check we're not set nitrous
|
|
dispDrv = gw.getDriverString()
|
|
if dispDrv == undefined do
|
|
(
|
|
messageBox ("WARNING! Viewport rendering not set to Direct3D. Tool will be unstable/unusable.") beep:true Title:"Display settings Error"
|
|
)
|
|
|
|
)
|
|
|
|
on keepHandsChk changed theState do
|
|
(
|
|
if keepHandsChk.state == true then
|
|
(
|
|
RsPreserveHandSkin = true
|
|
print "Twooo"
|
|
)
|
|
else
|
|
(
|
|
RsPreserveHandSkin = false
|
|
print "Fud"
|
|
)
|
|
)
|
|
|
|
on getTargetObjBtn picked obj do
|
|
(
|
|
mjrTarget = obj
|
|
|
|
select mjrTarget
|
|
max hide inv --hide unselected
|
|
|
|
skinXferBtn.enabled = true
|
|
)
|
|
|
|
on skinXferBtn pressed do
|
|
(
|
|
--first save out hand skinning data if we are preserving
|
|
if RsPreserveHandSkin == true do
|
|
(
|
|
outPutHandSkinData mjrTarget
|
|
)
|
|
|
|
print ("mjrTarget: "+(mjrTarget as string))
|
|
|
|
--nned to collapse the mjrTarget object.
|
|
collapseStack mjrTarget
|
|
-- addModifier mjrTarget (Skin())
|
|
|
|
importTemplateMesh mjrTarget templateCombo.selected
|
|
|
|
destroyDialog RStransferSkinDataUI
|
|
--now we're ready to do the skin data transfer
|
|
|
|
filein (::RsConfigGetWildwestDir() + "script/3dsmax/characters/rigging/skindatatransfer_UI.ms")
|
|
|
|
-- while skinXFerComplete == true do
|
|
-- (
|
|
-- if RsPreserveHandSkin == true do
|
|
-- (
|
|
-- inputHandSkinData targetObj
|
|
-- )
|
|
-- )
|
|
|
|
)
|
|
)
|
|
|
|
createDialog RStransferSkinDataUI |