tools/toolfcurveeditor/ortool_fcurveeditor_tool.cxx

tools/toolfcurveeditor/ortool_fcurveeditor_tool.cxx
// ===========================================================================
// Copyright 2017 Autodesk, Inc. All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk license
// agreement provided at the time of installation or download, or which
// otherwise accompanies this software in either electronic or hard copy form.
// ===========================================================================
#include <fbxsdk/scene/animation/fbxanimcurve.h>
#include <fbxsdk/scene/animation/fbxanimcurvenode.h>
#include <fbxsdk/scene/animation/fbxanimlayer.h>
#include <fbxsdk/scene/fbxscene.h>
#include <fbxsdk/core/fbxmanager.h>
#include <fbxsdk/core/fbxpropertydef.h>
#include <fbxsdk/fileio/fbximporter.h>
#include <fbxsdk/fileio/fbxexporter.h>
//--- Class declaration
#include "ortool_fcurveeditor_tool.h"
//--- Registration defines
#define ORTOOLTEMPLATE__CLASS ORTOOLTEMPLATE__CLASSNAME
#define ORTOOLTEMPLATE__LABEL "FCurveEditor"
#define ORTOOLTEMPLATE__DESC "FBSDK - Tool FCurve Editor Description"
//--- Implementation and registration
FBToolImplementation( ORTOOLTEMPLATE__CLASS );
FBRegisterTool ( ORTOOLTEMPLATE__CLASS,
ORTOOLTEMPLATE__LABEL,
ORTOOLTEMPLATE__DESC,
FB_DEFAULT_SDK_ICON ); // Icon filename (default=Open Reality icon)
using namespace FBXSDK_NAMESPACE;
/************************************************
* Constructor.
************************************************/
bool ORTool_FCurveEditor::FBCreate()
{
mPropertyFromFBSDKFromProperty = NULL;
mPropertyFromFBSDKFromANode = NULL;
mPropertyFromFBSDKOutsideEditor = NULL;
mPropertyFromFBXSDKProperty = NULL;
// Tool options
StartSize[0] = 800;
StartSize[1] = 500;
int lB = 10;
//int lS = 4;
int lW = 200;
int lH = 18;
// Configure layout
AddRegion( "Label", "Label",
lB, kFBAttachLeft, "", 1.0 ,
lB, kFBAttachTop, "", 1.0,
lW, kFBAttachNone, "", 1.0,
lH, kFBAttachNone, "", 1.0 );
SetControl( "Label", mLabel );
mLabel.Caption = "Custom curve shown in FCurveEditor";
AddRegion( "Delete", "Delete",
lB, kFBAttachLeft, "", 1.0 ,
30, kFBAttachTop, "", 1.0,
lW, kFBAttachNone, "", 1.0,
lH, kFBAttachNone, "", 1.0 );
SetControl( "Delete", mExternalFCurveButton );
mExternalFCurveButton.Caption = "Add new property";
mExternalFCurveButton.OnClick.Add( this, (FBCallback) &ORTool_FCurveEditor::EventExternalFCurveClick);
mExternalFCurveButtonState = 0;
AddRegion( "FCurveInteractionButton", "FCurveInteractionButton",
225, kFBAttachLeft, "", 1.0 ,
30, kFBAttachTop, "", 1.0,
lW, kFBAttachNone, "", 1.0,
lH, kFBAttachNone, "", 1.0 );
SetControl( "FCurveInteractionButton", mPropertyAndKeyButton );
mPropertyAndKeyButton.Caption = "Frame All";
mPropertyAndKeyButton.OnClick.Add( this, (FBCallback) &ORTool_FCurveEditor::EventPropertyAndKeyClick);
mPropertyAndKeyButtonButtonState = 0;
mEditor = new FBFCurveEditor();
AddRegion("FCurveEditor","FCurveEditor",
30, kFBAttachLeft, "", 1.0 ,
50, kFBAttachTop, "", 1.0,
-10, kFBAttachRight, "", 1.0,
-10, kFBAttachBottom, "", 1.0 );
SetControl("FCurveEditor",mEditor);
//Creating test data to show how to use the external fcurve support
//this is FBSDK data, we create a null that will have some animation
mNull = new FBModelNull("Source Object for curve");
mNull->Show = true;
FBTVector lPos(10, 20, 30);
FBTime lTime = FBTime(0);
mNull->Translation.SetAnimated(true);
mNull->Translation.GetAnimationNode()->KeyAdd(lTime, lPos.mValue);
FBRVector lR(5, 10, 15);
mNull->Rotation.SetAnimated(true);
mNull->Rotation.GetAnimationNode()->KeyAdd(lTime, lR.mValue);
//key on the layer 1
FBAnimationLayer* lLayer = FBSystem().CurrentTake->GetLayer(1);
if(!lLayer)
{
FBSystem().CurrentTake->CreateNewLayer();
lLayer = FBSystem().CurrentTake->GetLayer(1);
}
FBSystem().CurrentTake->SetCurrentLayer(1);
FBTVector lPosLayer1(40, 50, 60);
mNull->Translation.SetAnimated(true);
mNull->Translation.GetAnimationNode()->KeyAdd(lTime, lPosLayer1.mValue);
lTime.SetSecondDouble(5.0);
FBTVector lPosLayer2(20, 30, 10);
mNull->Translation.GetAnimationNode()->KeyAdd(lTime, lPosLayer2.mValue);
FBRVector lRLayer1(20, 30, 45);
mNull->Rotation.SetAnimated(true);
mNull->Rotation.GetAnimationNode()->KeyAdd(lTime, lRLayer1.mValue);
//add curve to the editor
mPropertyFromFBSDKFromANode = FBFCurveEditorUtility::TheOne().AddExternalCurves("FCurveDummyNode", "TestProp", kFBPT_Vector3D, mNull->Translation.GetAnimationNode());
//add curve to the editor
mPropertyFromFBSDKFromProperty = FBFCurveEditorUtility::TheOne().AddExternalCurves("FCurveDummyNode", "TestPropFromProp", (FBProperty*)&mNull->Translation);
//test with another editor with the same translation property
mPropertyFromFBSDKOutsideEditor = FBFCurveEditorUtility::TheOne().AddExternalCurves("FCurveDummyNode", "TestPropInOutsideEditor", kFBPT_Vector3D, mNull->Translation.GetAnimationNode(), mEditor);
//FBXSDK object
// create a SdkManager
FbxManager *lSdkManager = FBXSDK_NAMESPACE::FbxManager::Create();
// create an IOSettings object
FbxIOSettings * ios = FbxIOSettings::Create(lSdkManager, IOSROOT );
// create an empty scene
mScene = FBXSDK_NAMESPACE::FbxScene::Create(lSdkManager,"");
// Create an importer.
FbxImporter* lImporter = FbxImporter::Create(lSdkManager, "");
// Initialize the importer by providing a filename and the IOSettings to use
#ifdef KARCH_ENV_WIN
lImporter->Initialize("C:\\cube.fbx", -1, ios);
#else
lImporter->Initialize("/var/tmp/cube.fbx", -1, ios);
#endif
// Import the scene.
lImporter->Import(mScene);
// Destroy the importer.
lImporter->Destroy();
//Get the animation from the cube
FbxNode* lObject = mScene->FindNodeByName("Cube");
if(lObject)
{
mPropertyFromFBXSDKProperty = FBFCurveEditorUtility::TheOne().AddExternalCurves(lObject->GetName(), "Lcl Translation", &lObject->LclTranslation, mScene->GetCurrentAnimationStack());
}
//FCurve Editor property view API
//select the null and one of the key
mNull->Selected = true;
mNull->Translation.SetFocus(true);
mNull->Translation.GetAnimationNode()->Nodes[0]->FCurve->KeySetSelected(0, true);
//FCurve Editor event callback
FBFCurveEditorUtility::TheOne().RegisterToFCurveEditorEvent(this, (FBCallback)&ORTool_FCurveEditor::EventFCurveEditorEvent);
return true;
}
/************************************************
* Destruction function.
************************************************/
void ORTool_FCurveEditor::FBDestroy()
{
FBFCurveEditorUtility::TheOne().UnregisterToFCurveEditorEvent(this, (FBCallback)&ORTool_FCurveEditor::EventFCurveEditorEvent);
}
void ORTool_FCurveEditor::EventFCurveEditorEvent(HIRegister pSender, HKEvent pEvent)
{
FBFCurveEditorEvent lEvent(pEvent);
if(lEvent.EventType == kFBGhostKeep)
{
FBTrace( "FBFCurveEditorEvent received: kFBGhostKeep\n" );
}
else if(lEvent.EventType == kFBGhostSwap)
{
FBTrace( "FBFCurveEditorEvent received: kFBGhostSwap\n" );
}
else if(lEvent.EventType == kFBGhostClear)
{
FBTrace( "FBFCurveEditorEvent received: kFBGhostClear\n" );
}
else
{
FBTrace( "FBFCurveEditorEvent received: kFBUnspecified\n" );
}
}
void ORTool_FCurveEditor::EventPropertyAndKeyClick( HISender pSender, HKEvent pEvent )
{
mPropertyAndKeyButtonButtonState++;
switch(mPropertyAndKeyButtonButtonState)
{
case 0:
break;
case 1:
{
//Frame the FCurve Editor
FBFCurveEditorUtility::TheOne().Frame(false);
mPropertyAndKeyButton.Caption = "Get the time span";
}
break;
case 2:
{
//Get the FCurve Editor time span
FBTimeSpan lTS = FBFCurveEditorUtility::TheOne().GetTimeSpan();
FBTrace( "Time span retrieved:\n - Start time: %s\n - Stop time: %s\n", lTS.GetStart().GetTimeString(), lTS.GetStop().GetTimeString() );
mPropertyAndKeyButton.Caption = "Set the time span from 0 to 8 seconds";
}
break;
case 3:
{
//Set the FCurve Editor time span
FBTime lEightSeconds;
lEightSeconds.SetSecondDouble(8);
FBTimeSpan lNewTS(0, lEightSeconds);
FBFCurveEditorUtility::TheOne().SetTimeSpan(lNewTS);
mPropertyAndKeyButton.Caption = "Get the selected properties";
}
break;
case 4:
{
//Get the selected properties of the FCurve Editor
FBArrayTemplate<FBProperty *> lPropArray;
FBFCurveEditorUtility::TheOne().GetProperties(lPropArray, true);
int lNbProps = lPropArray.GetCount();
FBTrace( "Selected Properties Count: %d\n", lNbProps );
for( int i = 0; i < lNbProps; i++ )
FBTrace( " - %s\n", lPropArray[ i ]->GetName() );
mPropertyAndKeyButton.Caption = "Get the objects";
}
break;
case 5:
{
//Get the displayed object of the FCurve Editor
FBArrayTemplate<FBComponent *> lObjectArray;
FBFCurveEditorUtility::TheOne().GetObjects(lObjectArray);
int lNbObjects = lObjectArray.GetCount();
FBTrace( "Objects Count: %d\n", lNbObjects );
for( int i = 0; i < lNbObjects; i++ )
FBTrace( " - %s\n", lObjectArray[ i ]->GetFullName() );
mPropertyAndKeyButton.Caption = "Get the selected curve components";
}
break;
case 6:
{
//Get all the selected properties
FBArrayTemplate<FBProperty *> lPropArray;
FBFCurveEditorUtility::TheOne().GetProperties(lPropArray, true);
//Add all the displayed curves into an array
FBArrayTemplate<FBFCurve *> lFBFCurveArray;
FBStringList lFCurvesNames;
for(int i = 0; i < lPropArray.GetCount(); i++)
{
FBPropertyAnimatable* lAnimProp = (FBPropertyAnimatable*)lPropArray.GetAt(i);
if( lAnimProp->GetAnimationNode() )
{
if(lAnimProp->GetAnimationNode()->FCurve && lAnimProp->IsFocused())
{
lFBFCurveArray.Add(lAnimProp->GetAnimationNode()->FCurve);
lFCurvesNames.Add(lAnimProp->GetName());
}
else
{
int lNodeCount = lAnimProp->GetAnimationNode()->Nodes.GetCount();
for(int lCurveIter = 0; lCurveIter < lNodeCount; lCurveIter++)
{
if(lAnimProp->IsFocused() || lAnimProp->IsFocusedChild(lCurveIter))
{
lFBFCurveArray.Add(lAnimProp->GetAnimationNode()->Nodes[lCurveIter]->FCurve);
char lCurveName[ 1024 ];
sprintf_s( lCurveName, "%s (child %d)", lAnimProp->GetName(), lCurveIter );
lFCurvesNames.Add( lCurveName );
}
}
}
}
}
int lNbCurves = lFBFCurveArray.GetCount();
FBTrace( "Curves Count: %d\n", lNbCurves );
for( int i = 0; i < lNbCurves; i++ )
FBTrace( " - %s\n", lFCurvesNames[ i ]);
mPropertyAndKeyButton.Caption = "Select the first property/component";
}
break;
case 7:
{
//Unselect the selected properties components
FBArrayTemplate<FBProperty *> lPropArray;
FBFCurveEditorUtility::TheOne().GetProperties(lPropArray, true);
for(int i = 0; i < lPropArray.GetCount(); i++)
{
FBPropertyAnimatable* lAnimProp = (FBPropertyAnimatable*)lPropArray.GetAt(i);
lAnimProp->SetFocus( false );
}
//Select one property component
FBFCurveEditorUtility::TheOne().GetProperties(lPropArray, false);
if(lPropArray.GetCount())
{
FBPropertyAnimatable* lAnimProp = (FBPropertyAnimatable*)lPropArray.GetAt(0);
lAnimProp->SetFocusChild(0, true);
}
mPropertyAndKeyButton.Caption = "Key the first property/component";
}
break;
case 8:
{
//Select a key of a displayed curve
FBArrayTemplate<FBProperty *> lPropArray;
FBFCurveEditorUtility::TheOne().GetProperties(lPropArray, false);
if(lPropArray.GetCount())
{
FBPropertyAnimatable* lAnimProp = (FBPropertyAnimatable*)lPropArray.GetAt(0);
// Key it
lAnimProp->KeyAt( FBTime(0,0,0,0) );
lAnimProp->KeyAt( FBTime(0,0,0,5) );
if(lAnimProp->GetAnimationNode()->FCurve)
{
lAnimProp->GetAnimationNode()->FCurve->KeySetSelected(0, true);
lAnimProp->GetAnimationNode()->FCurve->KeySetSelected(1, true);
}
else
{
if(lAnimProp->GetAnimationNode()->Nodes.GetCount())
{
lAnimProp->GetAnimationNode()->Nodes[0]->FCurve->KeySetSelected(0, true);
lAnimProp->GetAnimationNode()->Nodes[0]->FCurve->KeySetSelected(1, true);
}
}
}
mPropertyAndKeyButton.Caption = "Frame selected keys";
}
break;
case 9:
{
// Frame on the selection
FBFCurveEditorUtility::TheOne().Frame( true );
mPropertyAndKeyButton.Caption = "Done";
}
break;
}
}
void ORTool_FCurveEditor::EventExternalFCurveClick( HISender pSender, HKEvent pEvent )
{
mExternalFCurveButtonState++;
switch(mExternalFCurveButtonState)
{
case 0:
break;
case 1:
mPropertyFromFBSDKAddedAfter = FBFCurveEditorUtility::TheOne().AddExternalCurves("FCurveDummyNode", "TestPropRotation", kFBPT_Vector3D, mNull->Rotation.GetAnimationNode());
mExternalFCurveButton.Caption = "Update Custom Curves";
break;
case 2:
{
//put the rotation into the translation to see if the curve will be transfered
FBFCurveEditorUtility::TheOne().UpdateCurves(mPropertyFromFBSDKAddedAfter, mNull->Rotation.GetAnimationNode());
//test the FBXSDK update functionality by adding a new key on the FBXSDK object and inject it into Mobu
FbxNode* lObject = mScene->FindNodeByName("Cube");
if(lObject)
{
FbxTime lTime;
lTime.SetSecondDouble(5.0);
lObject->LclTranslation.GetCurveNode(false)->GetCurve(0)->KeyAdd(lTime);
FBFCurveEditorUtility::TheOne().UpdateCurves(mPropertyFromFBXSDKProperty, &lObject->LclTranslation, NULL);
}
mExternalFCurveButton.Caption = "Get Custom Curves";
}
break;
case 3:
{
FBFCurveEditorUtility::TheOne().GetCurves(mPropertyFromFBSDKAddedAfter, mNull->Translation.GetAnimationNode());
//add new keys and transfer back to the fbx scene
FbxNode* lObject = mScene->FindNodeByName("Cube");
if(lObject)
{
FBSystem().CurrentTake->SetCurrentLayer(0);
FBTime lTime;
lTime.SetFrame(70);
FBTVector lPos(40, 50, 60);
FBPropertyAnimatable* lAnimProp = (FBPropertyAnimatable*)mPropertyFromFBXSDKProperty;
if( lAnimProp->GetAnimationNode() )
lAnimProp->GetAnimationNode()->KeyAdd(lTime, lPos.mValue);
FBSystem().CurrentTake->SetCurrentLayer(1);
lTime.SetFrame(50);
lAnimProp = (FBPropertyAnimatable*)mPropertyFromFBXSDKProperty;
if( lAnimProp->GetAnimationNode() )
lAnimProp->GetAnimationNode()->KeyAdd(lTime, lPos.mValue);
FBFCurveEditorUtility::TheOne().GetCurves(mPropertyFromFBXSDKProperty, &lObject->LclTranslation, mScene->GetCurrentAnimationStack());
// Export the scene into a new file to see if the model will have the new animation
// create a SdkManager
FbxManager *lSdkManager = FBXSDK_NAMESPACE::FbxManager::Create();
// create an IOSettings object
FbxIOSettings * ios = FbxIOSettings::Create(lSdkManager, IOSROOT );
// Create an exporter.
FbxExporter* lExporter = FbxExporter::Create(lSdkManager, "FBXExporter");
// Initialize the exporter by providing a filename and the IOSettings to use
#ifdef KARCH_ENV_WIN
lExporter->Initialize("C:\\Exported_cube.fbx", -1, ios);
#else
lExporter->Initialize("/var/tmp/Exported_cube.fbx", -1, ios);
#endif
// Export the scene.
lExporter->Export(mScene);
// Destroy the exporter.
lExporter->Destroy();
}
mExternalFCurveButton.Caption = "Delete Custom Object";
}
break;
case 4:
if(mPropertyFromFBSDKFromProperty)
{
FBFCurveEditorUtility::TheOne().RemoveExternalCurves(mPropertyFromFBSDKFromProperty);
mPropertyFromFBSDKFromProperty = NULL;
}
if(mPropertyFromFBSDKFromANode)
{
FBFCurveEditorUtility::TheOne().RemoveExternalCurves(mPropertyFromFBSDKFromANode);
mPropertyFromFBSDKFromANode = NULL;
}
if(mPropertyFromFBSDKOutsideEditor)
{
FBFCurveEditorUtility::TheOne().RemoveExternalCurves(mPropertyFromFBSDKOutsideEditor);
mPropertyFromFBSDKOutsideEditor = NULL;
}
if(mPropertyFromFBSDKAddedAfter)
{
FBFCurveEditorUtility::TheOne().RemoveExternalCurves(mPropertyFromFBSDKAddedAfter);
mPropertyFromFBSDKAddedAfter = NULL;
}
if(mPropertyFromFBXSDKProperty)
{
FBFCurveEditorUtility::TheOne().RemoveExternalCurves(mPropertyFromFBXSDKProperty);
mPropertyFromFBXSDKProperty = NULL;
}
mExternalFCurveButton.Caption = "Done";
break;
}
}