640 lines
24 KiB
Plaintext
Executable File
640 lines
24 KiB
Plaintext
Executable File
' FaceFXPlugin
|
|
' Initial code generated by XSI SDK Wizard
|
|
' Executed Sat Jan 12 12:33:21 EST 2008 by mbarrett
|
|
'
|
|
'
|
|
' Tip: The wizard only exposes a small subset of the possible controls
|
|
' and layout that can be achieved on a Property Page. To find out more
|
|
' please refer to the Object Model reference documentation for PPGLayout, PPG
|
|
' and CustomProperty
|
|
'
|
|
' Tip: Don't be concerned about achieving the exact ordering of the parameters
|
|
' because they can easily be reordered in the second phase.
|
|
'
|
|
' Tip: Use the "Refresh" option on the Property Page context menu to
|
|
' reload your script changes and re-execute the DefineLayout callback.
|
|
' Tip: To add a command to this plug-in, right-click in the
|
|
' script editor and choose Tools > Add Command.
|
|
'
|
|
' Tip: To get help on a callback, highlight the callback name
|
|
' (for example, "Init", "Define", or "Execute") and press F1.
|
|
|
|
function XSILoadPlugin( in_reg )
|
|
in_reg.Author = "mbarrett"
|
|
in_reg.Name = "FxXSIUI"
|
|
in_reg.Email = ""
|
|
in_reg.URL = ""
|
|
in_reg.Major = 1
|
|
in_reg.Minor = 1
|
|
in_reg.Help = XSIUtils.BuildPath( in_reg.OriginPath, "FxXSI.htm")
|
|
|
|
in_reg.RegisterProperty "FaceFX"
|
|
in_reg.RegisterMenu siMenuMainFileExportID, "Actor_Export",false
|
|
in_reg.RegisterMenu siMenuMainFileImportID, "Actor_Import",false
|
|
|
|
|
|
' This is called from the C++ plugin to update the GUI when appropriate
|
|
in_reg.RegisterCommand "FaceFX_Refresh_Script_GUI","FaceFX_Refresh_Script_GUI"
|
|
|
|
|
|
'RegistrationInsertionPoint - do not remove this line
|
|
|
|
XSILoadPlugin = true
|
|
end function
|
|
|
|
function XSIUnloadPlugin( in_reg )
|
|
dim strPluginName
|
|
strPluginName = in_reg.Name
|
|
Application.LogMessage strPluginName & " has been unloaded.",siVerbose
|
|
XSIUnloadPlugin = true
|
|
end function
|
|
|
|
function Actor_Export_Init( in_ctxt )
|
|
set oMenu = in_ctxt.source
|
|
oMenu.AddCallbackItem "FaceFX ...", "OnActorMenu"
|
|
end function
|
|
|
|
function Actor_Import_Init( in_ctxt )
|
|
set oMenu = in_ctxt.source
|
|
oMenu.AddCallbackItem "FaceFX ...", "OnActorMenu"
|
|
end function
|
|
|
|
|
|
function OnActorMenu( in_ctxt )
|
|
set oActorProp = ActiveSceneRoot.Properties("FaceFX")
|
|
if typename(oActorProp) <> "CustomProperty" then
|
|
set oActorProp = ActiveSceneRoot.AddProperty("FaceFX")
|
|
else
|
|
' Delete the existing property. If we don't do this, new GUI elements like NodeType don't show up.
|
|
DeleteObj oActorProp
|
|
set oActorProp = ActiveSceneRoot.AddProperty("FaceFX")
|
|
end if
|
|
InspectObj oActorProp
|
|
|
|
end function
|
|
|
|
|
|
'FaceFX property
|
|
function FaceFX_Define( in_ctxt )
|
|
dim oCustomProperty
|
|
set oCustomProperty = in_ctxt.Source
|
|
oCustomProperty.AddParameter2 "ReferenceBone",siInt4,0,,,,,siClassifUnknown,siPersistable
|
|
oCustomProperty.AddParameter2 "NodeType",siInt4,0,0,100,0,100,siClassifUnknown,siPersistable
|
|
oCustomProperty.AddParameter2 "Nodes",siInt4,0,,,,,siClassifUnknown,siPersistable
|
|
oCustomProperty.AddParameter2 "AnimationGroup",siInt4,0,0,100,0,100,siClassifUnknown,siPersistable
|
|
oCustomProperty.AddParameter2 "Animation",siInt4,0,0,100,0,100,siClassifUnknown,siPersistable
|
|
oCustomProperty.AddParameter2 "File",siString,"None",,,,,siClassifUnknown,siPersistable
|
|
FaceFX_Define = true
|
|
end function
|
|
|
|
|
|
|
|
function FaceFX_DefineLayout( in_ctxt )
|
|
dim oLayout,oItem
|
|
set oLayout = in_ctxt.Source
|
|
oLayout.Clear
|
|
oLayout.AddTab "Reference Pose"
|
|
set oItem = oLayout.AddEnumControl( "ReferenceBone",Array() , "", siControlListBox )
|
|
oItem.SetAttribute siUICY, 80
|
|
oLayout.AddRow
|
|
oLayout.AddButton "ImportReferencePose", "Import"
|
|
oLayout.AddButton "ExportReferencePose", "Export"
|
|
oLayout.EndRow
|
|
oLayout.AddTab "Nodes"
|
|
oLayout.AddRow
|
|
set oItem = oLayout.AddEnumControl( "NodeType",Array() , "", siControlCombo)
|
|
oLayout.EndRow
|
|
|
|
|
|
oLayout.AddRow
|
|
set oItem = oLayout.AddEnumControl( "Nodes",Array() , "", siControlListBox )
|
|
oLayout.EndRow
|
|
'oItem.SetAttribute siUICY, 80
|
|
oLayout.AddRow
|
|
oLayout.AddButton "ImportNodes", "Import"
|
|
oLayout.AddButton "ExportNodes", "Export"
|
|
oLayout.AddButton "BatchImportNodes", "Batch import..."
|
|
oLayout.AddButton "BatchExportNodes", "Batch export..."
|
|
oLayout.EndRow
|
|
oLayout.AddTab "Animations"
|
|
oLayout.AddRow
|
|
set oItem = oLayout.AddEnumControl( "AnimationGroup",Array() , "", siControlCombo)
|
|
oLayout.AddButton "InsertAnimGroup", "New"
|
|
oLayout.EndRow
|
|
'oItem.SetAttribute siUICY, 80
|
|
set oItem = oLayout.AddEnumControl( "Animation",Array() , "", siControlListBox)
|
|
'oItem.SetAttribute siUICY, 80
|
|
oLayout.AddRow
|
|
oLayout.AddButton "ImportAnimation", "Import"
|
|
oLayout.AddButton "Clean", "Clean"
|
|
oLayout.AddButton "RenameAnimation", "Rename"
|
|
oLayout.AddButton "DeleteAnimation", "Delete"
|
|
oLayout.EndRow
|
|
|
|
if FaceFXIsAnalysisTool then
|
|
oLayout.AddRow
|
|
oLayout.AddButton "GenerateAnimation", "Generate Animation"
|
|
oLayout.AddButton "NewTake", "New Take"
|
|
oLayout.EndRow
|
|
end if
|
|
|
|
oLayout.AddTab "File"
|
|
set oFileItem = oLayout.AddItem( "File",,siControlFilePath)
|
|
oFileItem.SetAttribute siUIFileFilter, "FaceFX Files |*.facefx:*.xml"
|
|
oFileItem.SetAttribute siUIOpenFile, true
|
|
oFileItem.SetAttribute siUIFileMustExist, true
|
|
oFileItem.SetAttribute siUIInitialDir, Application.InstallationPath( siUserPath )
|
|
oLayout.AddGroup
|
|
oLayout.AddRow
|
|
oLayout.AddButton "OpenActorFile", "Open"
|
|
oLayout.AddButton "SaveActorFile", "Save"
|
|
oLayout.AddButton "NewActorFile", "New"
|
|
if FaceFXIsAnalysisTool then
|
|
oLayout.AddButton "ChangeAnalysisActor", "Change Analysis Actor"
|
|
end if
|
|
oLayout.EndRow
|
|
oLayout.EndGroup
|
|
|
|
FaceFX_DefineLayout = true
|
|
end function
|
|
|
|
function FaceFX_Helper_ReadMixerContents( in_mixer, oMorphClips )
|
|
for each trk in in_mixer.Tracks
|
|
FaceFX_Helper_ReadClipsFromContainer trk, oMorphClips
|
|
next
|
|
end function
|
|
|
|
function FaceFX_Helper_ReadClipsFromContainer( in_can, oMorphClips )
|
|
for each clp in in_can.Clips
|
|
if clp.Type <> siClipShapeType then
|
|
for each trk in clp.Tracks
|
|
FaceFX_Helper_ReadClipsFromContainer trk, oMorphClips
|
|
next
|
|
elseif clp.Type <> siClipAnimationType then
|
|
oMorphClips.Add(clp)
|
|
end if
|
|
next
|
|
end function
|
|
|
|
function FaceFX_Helper_GetMorphTargetClips( oMorphClips )
|
|
' There are many ways to find the mixer we want to use to find morph targets.
|
|
' Below are a few examples.
|
|
|
|
' Look in the Scene root mixer
|
|
' FaceFX_Helper_ReadMixerContents ActiveSceneRoot.Mixer
|
|
|
|
' Look in all selected Model objects
|
|
'For Each obj in Selection
|
|
' if obj.IsClassOf(siModelID) then
|
|
' if obj.HasMixer() then
|
|
' FaceFX_Helper_ReadMixerContents obj.Mixer
|
|
' end if
|
|
' end if
|
|
'next
|
|
' This looks for all models in the scene
|
|
Set oRoot = ActiveSceneRoot
|
|
Set oMeshes = oRoot.FindChildren(,,si3DObjectFamily)
|
|
For Each mesh in oMeshes
|
|
if mesh.IsClassOf(siModelID) then
|
|
if mesh.HasMixer() then
|
|
FaceFX_Helper_ReadMixerContents mesh.Mixer, oMorphClips
|
|
end if
|
|
end if
|
|
next
|
|
end function
|
|
|
|
function FaceFX_Helper_ImportAnimationOntoMorphs( groupName, animName )
|
|
set oMorphClips = CreateObject( "XSI.Collection" )
|
|
FaceFX_Helper_GetMorphTargetClips oMorphClips
|
|
' Get a list of FxMorphTargetNodes from the actor file
|
|
sMorphNodes= FaceFXGetNodes( "FxMorphTargetNode")
|
|
endFrame = FaceFXGetAnimDuration( groupName, animName ) * GetValue( "PlayControl.Rate" )
|
|
For Each obj in oMorphClips
|
|
LogMessage "--- " & obj & " ---"
|
|
if Right(obj, 5) = "_Clip" then
|
|
targetname = Left(obj.name, Len(obj.name) - 5)
|
|
for each morphName in sMorphNodes
|
|
' FaceFX Studio matches the FxMorphTargetNode's "target" property with the XSI morph target name,
|
|
' But here we match the node's name to the XSI morph target name. When morph nodes are created,
|
|
' the node name matches the "target" property, but renaming the node or changing the target property
|
|
' can cause these two to get out of synch and FaceFX Studio and the plugin will then behave differently.
|
|
if targetname = morphName then
|
|
keyTimes = FaceFXGetBakedCurveKeyTimes( groupName , animName , targetname)
|
|
keyValues = FaceFXGetBakedCurveKeyValues( groupName , animName , targetname)
|
|
keySlopeIn = FaceFXGetBakedCurveKeySlopeIn( groupName , animName , targetname)
|
|
keySlopeOut = FaceFXGetBakedCurveKeySlopeOut( groupName , animName , targetname)
|
|
|
|
ReDim aCurveKeys( ubound(keyTimes) * 2 + 1 )
|
|
ReDim aCurveKeyTangents( ubound(keyTimes) * 4 + 3 )
|
|
prevKeyTime = 0
|
|
nextKeyTime = 0
|
|
if ubound(keyTimes) > 0 then
|
|
prevKeyTime = keyTimes(0) -.5
|
|
nextKeyTime = keyTimes(0) +.5
|
|
end if
|
|
if ubound(keyTimes) > 1 then
|
|
nextKeyTime = keyTimes(1)
|
|
end if
|
|
for i = 0 to ubound(keyTimes)
|
|
frame = keyTimes(i) * GetValue( "PlayControl.Rate" )
|
|
if i < ubound(keyTimes) then
|
|
nextKeyTime = keyTimes(i+1)
|
|
else
|
|
nextKeyTime = keyTimes(i)+ .5
|
|
end if
|
|
|
|
aCurveKeys(i*2) = frame
|
|
aCurveKeys(i*2 + 1) = keyValues(i)
|
|
|
|
aCurveKeyTangents(i*4) = (prevKeyTime - keyTimes(i)) * GetValue( "PlayControl.Rate" )/ 3
|
|
aCurveKeyTangents(i*4 +1) = (prevKeyTime - keyTimes(i)) * keySlopeIn(i) / 3
|
|
aCurveKeyTangents(i*4 +2) = (nextKeyTime - keyTimes(i)) * GetValue( "PlayControl.Rate" )/ 3
|
|
aCurveKeyTangents(i*4 +3) = (nextKeyTime - keyTimes(i)) * keySlopeOut(i) / 3
|
|
|
|
prevKeyTime = keyTimes(i)
|
|
next
|
|
set fCurve = obj.Parameters( "weight" ).AddFCurve2(aCurveKeys)
|
|
fCurve.SetKeyTangents(aCurveKeyTangents)
|
|
end if
|
|
next
|
|
end if
|
|
next
|
|
end function
|
|
|
|
function FaceFX_Helper_GetMorphTargetNames( )
|
|
set oMorphClips = CreateObject( "XSI.Collection" )
|
|
|
|
FaceFX_Helper_GetMorphTargetClips oMorphClips
|
|
dim oMorphTargetNames()
|
|
Redim oMorphTargetNames(oMorphClips.Count)
|
|
For Each obj in oMorphClips
|
|
int count = 0
|
|
if Right(obj, 5) = "_Clip" then
|
|
targetname = Left(obj.name, Len(obj.name) - 5)
|
|
oMorphTargetNames(count)= targetName
|
|
count = count+1
|
|
end if
|
|
Next
|
|
FaceFX_Helper_GetMorphTargetNames = oMorphTargetNames
|
|
end function
|
|
|
|
function FaceFX_Helper_GetNodeType()
|
|
nodeTypeName = ""
|
|
set oNodeTypeItem = PPG.PPGLayout.Item("NodeType")
|
|
aUIItems = oNodeTypeItem.UIitems
|
|
if ubound(aUIItems ) > 0 then
|
|
nodeTypeName = aUIItems(PPG.NodeType.Value *2)
|
|
end if
|
|
FaceFX_Helper_GetNodeType = nodeTypeName
|
|
end function
|
|
|
|
function FaceFX_Helper_GetAnimGroup()
|
|
animGroupName = ""
|
|
set oAnimationGroupItem = PPG.PPGLayout.Item("AnimationGroup")
|
|
aUIItems = oAnimationGroupItem.UIitems
|
|
if ubound(aUIItems ) > 0 then
|
|
animGroupName = aUIItems(PPG.AnimationGroup.Value *2)
|
|
end if
|
|
FaceFX_Helper_GetAnimGroup = animGroupName
|
|
end function
|
|
|
|
|
|
function FaceFX_OpenActorFile_OnClicked()
|
|
set filesys = CreateObject("Scripting.FileSystemObject")
|
|
if not(filesys.FileExists(PPG.File.Value)) then
|
|
set oFileBrowser = XSIUIToolkit.FileBrowser
|
|
|
|
oFileBrowser.DialogTitle = "Select a FaceFX actor file" ' set the title of the file browser
|
|
oFileBrowser.InitialDirectory = Application.InstallationPath( siUserPath )
|
|
oFileBrowser.Filter = "FaceFX Actor Files (*.facefx)|*.facefx|FaceFX XML Actor Files (*.xml)|*.xml||" '
|
|
oFileBrowser.ShowOpen ' show an open file dialog
|
|
PPG.File.Value = oFileBrowser.FilePathName
|
|
end if
|
|
if filesys.FileExists(PPG.File.Value) then
|
|
FaceFXOpenActor PPG.File.Value
|
|
FaceFX_OnInit
|
|
PPG.Refresh
|
|
end if
|
|
end function
|
|
|
|
function FaceFX_SaveActorFile_OnClicked()
|
|
bOverwrite = true
|
|
set filesys = CreateObject("Scripting.FileSystemObject")
|
|
if not Right(PPG.File.Value, 7) = ".facefx" and not Right(PPG.File.Value,4) = ".xml" then
|
|
set oFileBrowser = XSIUIToolkit.FileBrowser
|
|
oFileBrowser.DialogTitle = "Select a FaceFX Actor file" ' set the title of the file browser
|
|
oFileBrowser.InitialDirectory = Application.InstallationPath( siUserPath )
|
|
oFileBrowser.Filter = "FaceFX Actor Files (*.facefx)|*.facefx|FaceFX XML Actor Files (*.xml)|*.xml||" '
|
|
oFileBrowser.ShowSave ' show an open file dialog
|
|
PPG.File.Value = oFileBrowser.FilePathName
|
|
elseif filesys.FileExists(PPG.File.Value) then
|
|
buttonPressed = XSIUIToolkit.Msgbox( "File already exists do you want to overwrite it ?", siMsgYesNo or siMsgQuestion, "FaceFX Save")
|
|
if buttonPressed = siMsgNo then
|
|
bOverwrite = false
|
|
end if
|
|
end if
|
|
if bOverwrite and not PPG.File.Value = "" then
|
|
FaceFXSaveActor PPG.File.Value
|
|
end if
|
|
end function
|
|
|
|
function FaceFX_OnInit()
|
|
set oRefBonePoseItem = PPG.PPGLayout.Item("ReferenceBone")
|
|
set oNodeTypeItem = PPG.PPGLayout.Item("NodeType")
|
|
set oNodesItem = PPG.PPGLayout.Item("Nodes")
|
|
set oAnimationItem = PPG.PPGLayout.Item("Animation")
|
|
set oAnimationGroupsItem = PPG.PPGLayout.Item("AnimationGroup")
|
|
oRefBonePoseItem.UIItems = [""]
|
|
oNodesItem.UIItems = [""]
|
|
oAnimationGroupsItem.UIItems = [""]
|
|
oAnimationItem.UIItems = [""]
|
|
oNodeTypeItem.UIItems = [""]
|
|
|
|
' Don't change the order or items without updating FxToolXSI.cpp as well.
|
|
sNodeTypeChoices = Array("FxBonePoseNode", "FxMorphTargetNode", "FxCombinerNode")
|
|
|
|
if typename(sNodeTypeChoices) <> "Empty" then
|
|
dim nodeTypeChoicesUI
|
|
Redim nodeTypeChoicesUI(ubound(sNodeTypeChoices) * 2 + 1)
|
|
for i = 0 to ubound(sNodeTypeChoices)
|
|
nodeTypeChoicesUI(i*2) = sNodeTypeChoices(i)
|
|
nodeTypeChoicesUI(i*2+1) = i
|
|
next
|
|
oNodeTypeItem.UIItems = nodeTypeChoicesUI
|
|
end if
|
|
|
|
animGroupName = FaceFX_Helper_GetAnimGroup
|
|
sRefBonePoses = FaceFXListRefBonePoses
|
|
if typename(sRefBonePoses) <> "Empty" then
|
|
if ubound(sRefBonePoses) >= 0 then
|
|
|
|
dim aRefBonePoseUI
|
|
Redim aRefBonePoseUI(ubound(sRefBonePoses) * 2 + 1)
|
|
for i = 0 to ubound(sRefBonePoses)
|
|
aRefBonePoseUI(i*2) = sRefBonePoses(i)
|
|
aRefBonePoseUI(i*2+1) = i
|
|
next
|
|
oRefBonePoseItem.UIItems = aRefBonePoseUI
|
|
end if
|
|
end if
|
|
sNodes = FaceFXGetNodes("FxBonePoseNode")
|
|
if typename(sNodes) <> "Empty" then
|
|
if ubound(sNodes) >= 0 then
|
|
|
|
dim aNodesUI
|
|
Redim aNodesUI(ubound(sNodes) * 2 + 1)
|
|
for i = 0 to ubound(sNodes)
|
|
aNodesUI(i*2) = sNodes(i)
|
|
aNodesUI(i*2+1) = i
|
|
next
|
|
oNodesItem.UIItems = aNodesUI
|
|
end if
|
|
end if
|
|
sAnimationGroups = FaceFXListAnimationGroups
|
|
if typename(sAnimationGroups) <> "Empty" then
|
|
if ubound(sAnimationGroups ) >= 0 then
|
|
|
|
dim aAnimationGroupsUI
|
|
Redim aAnimationGroupsUI(ubound(sAnimationGroups) * 2 + 1)
|
|
for i = 0 to ubound(sAnimationGroups)
|
|
aAnimationGroupsUI(i*2) = sAnimationGroups(i)
|
|
aAnimationGroupsUI(i*2+1) = i
|
|
next
|
|
oAnimationGroupsItem.UIItems = aAnimationGroupsUI
|
|
|
|
sAnimations = FaceFXListAnimationsFromGroup(sAnimationGroups(0))
|
|
if Ubound(sAnimations) >= 0 then
|
|
|
|
dim aAnimationUI
|
|
Redim aAnimationUI(ubound(sAnimations) * 2 + 1)
|
|
for i = 0 to ubound(sAnimations)
|
|
aAnimationUI(i*2) = sAnimations(i)
|
|
aAnimationUI(i*2+1) = i
|
|
next
|
|
oAnimationItem.UIItems = aAnimationUI
|
|
end if
|
|
end if
|
|
end if
|
|
PPG.Refresh
|
|
end function
|
|
|
|
function FaceFX_ImportReferencePose_OnClicked()
|
|
FaceFXImportRefBonePose Dictionary.GetObject("PlayControl").Current.value
|
|
end function
|
|
|
|
function FaceFX_ExportReferencePose_OnClicked()
|
|
FaceFXExportRefBonePose
|
|
FaceFX_RefBones_OnChanged
|
|
end function
|
|
|
|
function FaceFX_ImportNodes_OnClicked()
|
|
set oBonePoseItem = PPG.PPGLayout.Item("Nodes")
|
|
aUIItems = oBonePoseItem.UIitems
|
|
poseName = aUIItems(PPG.Nodes.value*2)
|
|
FaceFXImportBonePose poseName, Dictionary.GetObject("PlayControl").Current.value
|
|
end function
|
|
|
|
|
|
function FaceFX_ExportNodes_OnClicked()
|
|
nodeName = InputBox("Node name", "FaceFX new node name","poseActor")
|
|
if nodeName <> "" then
|
|
selectedNodeType = FaceFX_Helper_GetNodeType
|
|
if selectedNodeType = "FxBonePoseNode" then
|
|
FaceFXExportBonePose Dictionary.GetObject("PlayControl").Current.value, nodeName
|
|
elseif selectedNodeType = "FxCombinerNode" then
|
|
FaceFXCreateNode nodeName, selectedNodeType, -1, 1
|
|
else
|
|
FaceFXCreateNode nodeName, selectedNodeType, 0, 1
|
|
end if
|
|
FaceFX_NodeType_OnChanged()
|
|
end if
|
|
PPG.Refresh
|
|
end function
|
|
|
|
function ShowDialogFileOpen()
|
|
set oFileBrowser = XSIUIToolkit.FileBrowser
|
|
|
|
oFileBrowser.DialogTitle = "Select a FaceFX pose batch file" ' set the title of the file browser
|
|
oFileBrowser.InitialDirectory = Application.InstallationPath( siUserPath )
|
|
oFileBrowser.Filter = "All Files (*.txt)|*.txt||" ' Allow selection of txt files
|
|
oFileBrowser.ShowOpen ' show an open file dialog
|
|
|
|
ShowDialogFileOpen = oFileBrowser.FilePathName
|
|
end function
|
|
|
|
function FaceFX_BatchImportNodes_OnClicked()
|
|
fileName = ShowDialogFileOpen()
|
|
if fileName <> "" then
|
|
FaceFXBatchImportNodes fileName
|
|
end if
|
|
end function
|
|
|
|
function FaceFX_BatchExportNodes_OnClicked()
|
|
|
|
selectedNodeType = FaceFX_Helper_GetNodeType
|
|
|
|
if selectedNodeType = "FxMorphTargetNode" then
|
|
sMorphTargets = FaceFX_Helper_GetMorphTargetNames
|
|
for i = 0 to ubound(sMorphTargets)
|
|
FaceFXCreateNode sMorphTargets(i), "FxMorphTargetNode", 0, 1
|
|
next
|
|
FaceFX_NodeType_OnChanged()
|
|
end if
|
|
if selectedNodeType = "FxBonePoseNode" then
|
|
fileName = ShowDialogFileOpen()
|
|
if fileName <> "" then
|
|
FaceFXBatchExportBonePoses fileName
|
|
end if
|
|
FaceFX_NodeType_OnChanged()
|
|
end if
|
|
|
|
PPG.Refresh
|
|
end function
|
|
|
|
function FaceFX_ImportAnimation_OnClicked()
|
|
animGroupName = FaceFX_Helper_GetAnimGroup
|
|
set oAnimations = PPG.PPGLayout.Item("Animation")
|
|
aUIItemsAnimation = oAnimations.UIitems
|
|
animationName = aUIItemsAnimation(PPG.Animation.Value*2)
|
|
frameRate = Application.ActiveProject.Properties("Play Control").Rate.Value
|
|
audioStartTime = (Dictionary.GetObject("PlayControl").Current.value) / (frameRate)
|
|
FaceFXImportAnimation animGroupName, animationName, frameRate, audioStartTime
|
|
' Insert keys onto morph targets with the below script function
|
|
FaceFX_Helper_ImportAnimationOntoMorphs animGroupName, animationName
|
|
end function
|
|
|
|
function FaceFX_Clean_OnClicked()
|
|
FaceFXClean
|
|
end function
|
|
|
|
function FaceFX_InsertAnimGroup_OnClicked()
|
|
groupName = InputBox("Enter new animation group name:", "New animation group name","newAnimGroup")
|
|
if groupName <> "" then
|
|
FaceFXInsertAnimGroup groupName
|
|
end if
|
|
FaceFX_OnInit
|
|
FaceFX_AnimationGroup_OnChanged
|
|
end function
|
|
|
|
function FaceFX_RenameAnimation_OnClicked()
|
|
animGroupName = FaceFX_Helper_GetAnimGroup
|
|
set oAnimations = PPG.PPGLayout.Item("Animation")
|
|
aUIItemsAnimation = oAnimations.UIitems
|
|
animationName = aUIItemsAnimation(PPG.Animation.Value*2)
|
|
newAnimationName = animationName
|
|
newAnimationName = InputBox("New animation name", "FaceFX new aniamtion name",newAnimationName)
|
|
if newAnimationName <> "" then
|
|
FaceFXRenameAnim animGroupName, animationName, newAnimationName
|
|
end if
|
|
FaceFX_AnimationGroup_OnChanged
|
|
end function
|
|
|
|
function FaceFX_DeleteAnimation_OnClicked()
|
|
animGroupName = FaceFX_Helper_GetAnimGroup
|
|
set oAnimations = PPG.PPGLayout.Item("Animation")
|
|
aUIItemsAnimation = oAnimations.UIitems
|
|
animationName = aUIItemsAnimation(PPG.Animation.Value*2)
|
|
FaceFXDeleteAnim animGroupName, animationName
|
|
FaceFX_AnimationGroup_OnChanged
|
|
end function
|
|
|
|
function FaceFX_GenerateAnimation_OnClicked()
|
|
animGroupName = FaceFX_Helper_GetAnimGroup
|
|
FaceFXGenerateAnim animGroupName
|
|
FaceFX_AnimationGroup_OnChanged
|
|
end function
|
|
|
|
function FaceFX_ChangeAnalysisActor_OnClicked()
|
|
set oFileBrowser = XSIUIToolkit.FileBrowser
|
|
oFileBrowser.DialogTitle = "Select an analysis actor" ' set the title of the file browser
|
|
oFileBrowser.InitialDirectory = Application.InstallationPath( siUserPath )
|
|
oFileBrowser.Filter = "FaceFX Actor Files (*.facefx)|*.facefx||"
|
|
oFileBrowser.ShowOpen ' show an open file dialog
|
|
|
|
set filesys = CreateObject("Scripting.FileSystemObject")
|
|
if filesys.FileExists(oFileBrowser.FilePathName) then
|
|
FaceFXChangeAnalysisActor oFileBrowser.FilePathName
|
|
end if
|
|
end function
|
|
|
|
function FaceFX_NewTake_OnClicked()
|
|
animGroupName = FaceFX_Helper_GetAnimGroup
|
|
set oAnimations = PPG.PPGLayout.Item("Animation")
|
|
aUIItemsAnimation = oAnimations.UIitems
|
|
animationName = aUIItemsAnimation(PPG.Animation.Value*2)
|
|
'Since start time is not less than end time, we'll get a new take of the entire animation.
|
|
FaceFXNewTake animGroupName, animationName, 0, 0
|
|
end function
|
|
|
|
function FaceFX_NewActorFile_OnClicked()
|
|
actorName = InputBox("New actor name", "FaceFX new actor name","newActor")
|
|
FaceFXNewActor actorName
|
|
PPG.File.value = actorName & ".facefx"
|
|
FaceFX_OnInit
|
|
end function
|
|
|
|
|
|
function FaceFX_RefBones_OnChanged()
|
|
set oRefBonePoseItem = PPG.PPGLayout.Item("ReferenceBone")
|
|
oRefBonePoseItem.UIItems = [""]
|
|
sRefBonePoses = FaceFXListRefBonePoses
|
|
if typename(sRefBonePoses) <> "Empty" then
|
|
if ubound(sRefBonePoses) >= 0 then
|
|
|
|
dim aRefBonePoseUI
|
|
Redim aRefBonePoseUI(ubound(sRefBonePoses) * 2 + 1)
|
|
for i = 0 to ubound(sRefBonePoses)
|
|
aRefBonePoseUI(i*2) = sRefBonePoses(i)
|
|
aRefBonePoseUI(i*2+1) = i
|
|
next
|
|
oRefBonePoseItem.UIItems = aRefBonePoseUI
|
|
end if
|
|
end if
|
|
PPG.Refresh
|
|
end function
|
|
|
|
|
|
|
|
function FaceFX_NodeType_OnChanged()
|
|
nodeTypeName = FaceFX_Helper_GetNodeType
|
|
sNodes = FaceFXGetNodes(nodeTypeName)
|
|
dim aUIItems
|
|
Redim aUIItems(ubound(sNodes) *2 +1)
|
|
for i = 0 to ubound(sNodes)
|
|
aUIItems(i*2) = sNodes(i)
|
|
aUIItems(i*2+1) = i
|
|
next
|
|
set oNodes = PPG.PPGLayout.Item("Nodes")
|
|
oNodes.UIitems = aUIItems
|
|
PPG.Refresh
|
|
end function
|
|
|
|
|
|
function FaceFX_AnimationGroup_OnChanged()
|
|
animGroupName = FaceFX_Helper_GetAnimGroup
|
|
sAnimations = FaceFXListAnimationsFromGroup(animGroupName)
|
|
dim aUIItems
|
|
Redim aUIItems(ubound(sAnimations) *2 +1)
|
|
for i = 0 to ubound(sAnimations)
|
|
aUIItems(i*2) = sAnimations(i)
|
|
aUIItems(i*2+1) = i
|
|
next
|
|
set oAnimations = PPG.PPGLayout.Item("Animation")
|
|
oAnimations.UIitems = aUIItems
|
|
PPG.Refresh
|
|
end function
|
|
|
|
|
|
|
|
function FaceFX_Refresh_Script_GUI_Init ( in_ctxt )
|
|
|
|
end function
|
|
|
|
function FaceFX_Refresh_Script_GUI_Execute ()
|
|
|
|
'set oActorProp = ActiveSceneRoot.Properties("FaceFX")
|
|
PPG.Refresh
|
|
FaceFX_RefBones_OnChanged
|
|
FaceFX_NodeType_OnChanged
|
|
FaceFX_AnimationGroup_OnChanged
|
|
end function |