Files
gtav-src/tools_ng/dcc/current/max2012/scripts/pipeline/util/skinutils.ms
T
2025-09-29 00:52:08 +02:00

354 lines
9.7 KiB
Plaintext
Executable File

--
-- File:: pipeline/util/skinutils.ms
-- Description:: Skin modifier utilities
--
-- Author:: David Muir <david.muir@rockstarnorth.com>
-- Date:: 7 July 2009
--
-----------------------------------------------------------------------------
-- Uses
-----------------------------------------------------------------------------
--filein "pipeline/util/file.ms" -- loaded on startup by startup.ms
-----------------------------------------------------------------------------
-- Functions
-----------------------------------------------------------------------------
--
-- utility: RsSkinUtils
-- desc: Skin modifier utilities
--
utility RsSkinUtils "RsSkinUtils"
(
--
-- name: HasSkin
-- desc: Return true if object has Skin modifier, false otherwise.
--
fn HasSkin obj = (
( obj.modifiers[#Skin] != undefined )
)
fn RsIsBoneRec obj =
(
if undefined!=obj.parent and (RsIsBoneRec obj.parent) then return true
else if (IsBone obj) then return true
else return false
)
fn IsBone obj =
(
local skinrefs = #()
skinrefs = for ref in (refs.dependents obj) where not isDeleted ref and Skin==(classof ref) collect ref
if skinrefs.count>0 then
(
return true
)
return false
)
--
-- name: BakeAndSaveWeights
-- desc: Bake vertex weights and save to filename
--
fn BakeAndSaveWeights obj filename = (
local result = false
if ( HasSkin obj ) then
(
setCommandPanelTaskMode #modify
modPanel.setCurrentObject obj.modifiers[#Skin]
subobjectLevel = 1
obj.modifiers[#Skin].Filter_Vertices = true
local nSkinVerts = skinOps.getNumberVertices obj.modifiers[#Skin]
skinOps.SelectVertices obj.modifiers[#Skin] #{1..nSkinVerts}
skinOps.bakeSelectedVerts obj.modifiers[#Skin]
RsMakeSurePathExists filename
skinOps.saveEnvelope obj.modifiers[#Skin] filename
subobjectlevel = 0
result = true
)
result
)
--
-- name: SkinAndLoadWeights
-- desc: Create Skin modifier and load vertex weights from filename
--
fn SkinAndLoadWeights obj filename bone_list match_by_name:false bone_limit:4 = (
setCommandPanelTaskMode #modify
skinMod = Skin()
skinMod.bone_Limit = bone_limit
skinMod.showNoEnvelopes = true
addModifier obj skinMod
subobjectLevel = 1
modPanel.setCurrentObject obj.modifiers[#Skin]
-- Prior to loading the weights, if we are matching by name then we
-- install a handler to press the Match By Name button on the load
-- dialog.
if ( match_by_name ) then
(
DialogMonitorOPS.RegisterNotification RsSkinUtils.__LoadEnvMatchByNameCallback ID:#SkinAndLoadWeightsCallback
DialogMonitorOPS.Enabled = true
)
for b in bone_list do
try ( skinOps.addBone obj.modifiers[#Skin] b 1 ) catch ()
completeRedraw()
skinOps.loadEnvelope obj.modifiers[#Skin] filename
-- Uninstall the dialog callback.
if ( match_by_name ) then
(
DialogMonitorOPS.Enabled = false
DialogMonitorOPS.UnregisterNotification ID:#SkinAndLoadWeightsCallback
)
subobjectLevel = 0
true
)
--
-- name: CollectBoneNamesInSkeleton
-- desc: Collects all of the done names that are currently in the skeleton hierarchy
-- starting at the given root bone and travelling down
--
fn CollectBoneNamesInSkeleton rootBone boneNames =
(
append boneNames rootBone.name
boneChildren = rootBone.children
for boneChild in boneChildren do
(
CollectBoneNamesInSkeleton boneChild boneNames
)
)
--
-- name: ValidateSkeletonForGeometry
-- desc: Validates that the bones attached to the models
-- skin modifier are all present in the skeleton hierarchy
--
fn ValidateBonesInHierarchy obj messages = (
-- check to see if a skin modifier exists
objectModifiers = obj.modifiers
skinModifier = undefined
for objModifier in objectModifiers do
(
if classof objModifier == skin Then
(
skinModifier = objModifier
)
)
if skinModifier == undefined then
(
-- Can export a prop without a skin modifier on it
return true
)
-- Create an array of the bones in the scene that are attached to the object
sceneBone = for obj in objects where (refs.dependencyLoopTest skinModifier obj) collect obj
if sceneBone.count == 0 Then
(
if messages != undefined Then
(
append messages "Couldn't find any bones in the scene that the skin modifier depends on."
)
return false
)
-- Pick any bone, find the root bone and then collect the names in the scene hierarchy starting at that root bone
rootSkeletonBone = sceneBone[1]
while rootSkeletonBone.parent != undefined do
(
rootSkeletonBone = rootSkeletonBone.parent
)
hierarchyBoneNames = #()
CollectBoneNamesInSkeleton rootSkeletonBone hierarchyBoneNames
-- make sure the skin modifier is selected and retrieve the bone count
max modify mode
modpanel.setCurrentObject skinModifier
boneCount = skinOps.GetNumberBones skinModifier
if boneCount == 0 Then
(
if messages != undefined Then
(
append messages "Skin modifier doesn't have any bones attached to it."
)
return false
)
-- Cycle through the skin bones and check them against the hierarchy
errorFound = false
for i = 1 to boneCount do
(
boneName = (skinOps.GetBoneName skinModifier i 1)
boneFound = false
for hierarchyBoneName in hierarchyBoneNames do
(
if boneName == hierarchyBoneName Then
(
boneFound = true
)
)
if boneFound == false Then
(
if not errorFound Then
(
if messages != undefined Then
(
append messages "Unable to export due the fact that the following bones were not found in the hierarchy:"
)
errorFound = true
)
if messages != undefined Then
(
append messages boneName
)
)
)
if errorFound then
(
return false
)
true
)
--
-- name: TestSkinObjectDuringMapTest
-- desc: Checks a object that has a skin modifier to make sure it is
-- valid for a map export
--
fn TestSkinObjectDuringMapTest obj skinMod messages =
(
local finish = false
-- get local infomation
local boneCount = 0
local boneNames = #()
local rootSkeletonBone = undefined
if finish == false and skinMod != undefined Then
(
progressend()
max modify mode
setCommandPanelTaskMode #modify
modpanel.setCurrentObject skinMod
boneCount = skinOps.getNumberBones skinMod
for i = 1 to boneCount do
(
boneName = skinOps.GetBoneName skinMod i 1
append boneNames boneName
)
progressStart "testing map objects"
)
-- Make sure that there are bones in the object
if finish == false and skinMod != undefined Then
(
if ( ( Skin == ( classof skinMod ) ) and ( 0 == boneCount ) ) then
(
messages = ( obj.name + " has skin modifier but no bones defined." )
return false
)
)
-- Make sure that all the bones are located inside the node hierarchy
if finish == false and skinMod != undefined Then
(
local errorFound = false
-- Create an array of the bones in the scene that are attached to the object and find the root
sceneBone = for obj in objects where (refs.dependencyLoopTest skinMod obj) collect obj
rootSkeletonBone = sceneBone[1]
while rootSkeletonBone.parent != undefined do
(
rootSkeletonBone = rootSkeletonBone.parent
)
hierarchyBoneNames = #()
CollectBoneNamesInSkeleton rootSkeletonBone hierarchyBoneNames
-- Cycle through the skin bones and check them against the hierarchy
for i = 1 to boneCount do
(
boneName = boneNames[i]
boneFound = false
for hierarchyBoneName in hierarchyBoneNames do
(
if boneName == hierarchyBoneName Then
(
boneFound = true
)
)
if boneFound == false Then
(
if messages != undefined Then
(
message = ("" + (obj.name) + " has a bone (" + boneName + ") attached to it that's not in the node hierarchy")
append messages message
errorFound = true
)
)
)
if errorFound == true then
(
return false
)
)
-- Check to see if the pivot on the object and the root bone match
if finish == false and skinMod != undefined and rootSkeletonBone != undefined Then
(
rootBonePivot = rootSkeletonBone.pos
objectPivot = obj.pos
if not rootBonePivot == objectPivot Then
(
message = ("" + (obj.name) + " pivot is not located in the same position as the root bone (" + rootSkeletonBone.name + ") pivot")
append messages message
)
rootBonePivot = rootSkeletonBone.rotation
objectPivot = obj.rotation
if not rootBonePivot == objectPivot Then
(
message = ("" + (obj.name) + " pivot doesn't have the same rotation as the root bone (" + rootSkeletonBone.name + ") pivot")
append messages message
)
)
true
)
-------------------------------------------------------------------------
-- Private (seriously, DO NOT USE)
-------------------------------------------------------------------------
--
-- name: __LoadEnvMatchByNameCallback
-- desc: dialog voodoo to press the "Match By Name" button on load env dialog.
--
fn __LoadEnvMatchByNameCallback = (
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
)
)
-- pipeline/util/skinutils.ms