tools/toolcustomtangent/ortool_customtangent_tool.cxx

tools/toolcustomtangent/ortool_customtangent_tool.cxx
// ===========================================================================
// Copyright 2016 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/fbxscene.h>
#include <fbxsdk/scene/animation/fbxanimcurve.h>
//--- Class declaration
#include "ortool_customtangent_tool.h"
//--- Registration defines
#define ORTOOLTEMPLATE__CLASS ORTOOLTEMPLATE__CLASSNAME
#define ORTOOLTEMPLATE__LABEL "CustomTangent"
#define ORTOOLTEMPLATE__DESC "FBSDK - Tool Custom Tangente Description"
//--- Implementation and registration
FBToolImplementation( ORTOOLTEMPLATE__CLASS );
FBRegisterTool ( ORTOOLTEMPLATE__CLASS,
ORTOOLTEMPLATE__LABEL,
ORTOOLTEMPLATE__DESC,
FB_DEFAULT_SDK_ICON ); // Icon filename (default=Open Reality icon)
#define VAR_NOT_USED(X) (void)X;
/************************************************
* Constructor.
************************************************/
bool ORTool_CustomTangent::FBCreate()
{
// Tool options
StartSize[0] = 160;
StartSize[1] = 95;
int lB = 10;
//int lS = 4;
int lW = 150;
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 tangents registered";
FBFCurveCustomTangentManager::TheOne().AddCustomTangentType("Tangent1", "FBXTangent1");
FBFCurveCustomTangentManager::TheOne().AddCustomTangentType("Tangent2", "FBXTangent2");
//register to the custom key evaluation callback
FBFCurveCustomTangentManager::TheOne().OnEvaluate.Add(this, (FBCallback) &ORTool_CustomTangent::EventEvaluate);
//register to the callback that will be called when a custom key is added
FBFCurveCustomTangentManager::TheOne().OnCustomKeyAdd.Add(this, (FBCallback) &ORTool_CustomTangent::EventKeyAdd);
//register to the callback that will be called when a generic key is added
FBFCurveCustomTangentManager::TheOne().OnKeyAdd.Add(this, (FBCallback) &ORTool_CustomTangent::EventKeyAddGeneric);
//register to the callback that will be called when a key interpolation is changed to a custom value
FBFCurveCustomTangentManager::TheOne().OnCustomKeyChange.Add(this, (FBCallback) &ORTool_CustomTangent::EventKeyChange);
return true;
}
/************************************************
* Destruction function.
************************************************/
void ORTool_CustomTangent::FBDestroy()
{
// Remove tool callbacks
FBFCurveCustomTangentManager::TheOne().OnEvaluate.Remove( this, (FBCallback) &ORTool_CustomTangent::EventEvaluate);
FBFCurveCustomTangentManager::TheOne().OnCustomKeyAdd.Remove( this, (FBCallback) &ORTool_CustomTangent::EventKeyAdd);
FBFCurveCustomTangentManager::TheOne().OnKeyAdd.Remove( this, (FBCallback) &ORTool_CustomTangent::EventKeyAdd);
FBFCurveCustomTangentManager::TheOne().OnCustomKeyChange.Remove( this, (FBCallback) &ORTool_CustomTangent::EventKeyChange);
// Free user allocated memory
}
void ORTool_CustomTangent::EventEvaluate( HISender pSender, HKEvent pEvent )
{
FBCurveEvaluationEvent lEvent(pEvent);
double lIndex = lEvent.KeyIndex;
double lKeyBeforeIndex = floor(lIndex);
double lKeyAfterIndex = ceil(lIndex);
FBFCurve* lCurve = lEvent.Curve;
FBXSDK_NAMESPACE::FbxAnimCurve* lFBXCurve = lEvent.GetFBXCurve();
if(lKeyBeforeIndex == lKeyAfterIndex)
{
//right on key
if(lCurve)
{
//You can use FBFCurveKey, but the performance will be much slower
//FBFCurveKey lKey = lCurve->Keys.GetAt(lKeyBeforeIndex);
//lEvent.Result = lKey.Value;
//Getting the value from the curve prevents the allocation of a FBFCurveKey
lEvent.Result = lCurve->KeyGetValue(lKeyBeforeIndex);
return;
}
else
{
lEvent.Result = lFBXCurve->KeyGet(lKeyBeforeIndex).GetValue();
return;
}
}
else
{
if(lCurve)
{
int lTangentIndex = lCurve->KeyGetTangentCustomIndex(lKeyBeforeIndex);
if(lTangentIndex == kFBTangentCustomIndex0)
{
//interpolate between the two keys
double lRatio = lIndex - lKeyBeforeIndex;
//linear interpolation between the two keys
lEvent.Result = ((lCurve->KeyGetValue(lKeyAfterIndex) - lCurve->KeyGetValue(lKeyBeforeIndex)) * lRatio) + lCurve->KeyGetValue(lKeyBeforeIndex);
return;
}
else if(lTangentIndex == kFBTangentCustomIndex1)
{
//interpolate between the two keys
double lRatio = lIndex - lKeyBeforeIndex;
//linear interpolation + offset between the two keys
lEvent.Result = ((lCurve->KeyGetValue(lKeyAfterIndex) - lCurve->KeyGetValue(lKeyBeforeIndex)) * lRatio) + lCurve->KeyGetValue(lKeyBeforeIndex);
if(lRatio < 0.5)
{
lEvent.Result = lEvent.Result + lRatio* 30.;
}
else
{
lEvent.Result = lEvent.Result + (lRatio-1.) * 30.;
}
return;
}
}
else
{
FBXSDK_NAMESPACE::FbxAnimCurveKey lKey = lFBXCurve->KeyGet(lKeyBeforeIndex);
FBXSDK_NAMESPACE::FbxAnimCurveKey lNextKey = lFBXCurve->KeyGet(lKeyAfterIndex);
int lTangentIndex = lEvent.LeftCustomTangentTypeIndex;
if(lTangentIndex == kFBTangentCustomIndex0)
{
//interpolate between the two keys
double lRatio = lIndex - lKeyBeforeIndex;
//linear interpolation between the two keys
lEvent.Result = ((lNextKey.GetValue() - lKey.GetValue()) * lRatio) + lKey.GetValue();
return;
}
else if(lTangentIndex == kFBTangentCustomIndex1)
{
//interpolate between the two keys
double lRatio = lIndex - lKeyBeforeIndex;
//linear interpolation + offset between the two keys
lEvent.Result = ((lNextKey.GetValue() - lKey.GetValue()) * lRatio) + lKey.GetValue();
if(lRatio < 0.5)
{
lEvent.Result = lEvent.Result + lRatio* 30.;
}
else
{
lEvent.Result = lEvent.Result + (lRatio-1.) * 30.;
}
return;
}
}
}
lEvent.Result = 0;
}
void ORTool_CustomTangent::EventKeyAdd( HISender pSender, HKEvent pEvent )
{
FBCurveCustomKeyAddEvent lEvent(pEvent);
//index of the key with a custom tangent that was added
int lIndex = lEvent.KeyIndex;
int lKeyBeforeIndex = lIndex -1;
int lKeyAfterIndex = lIndex + 1;
FBFCurve* lCurve = lEvent.Curve;
if(lCurve)
{
if(lCurve->Keys.GetCount() > lKeyAfterIndex)
{
//adjust settings based on the next key if needed
}
if(lKeyBeforeIndex >= 0)
{
//adjust settings based on the previous key if needed
}
lCurve->KeySetLeftTangentWeight(lIndex, 30);
lCurve->KeySetRightTangentWeight(lIndex, 30);
lCurve->KeySetLeftBezierTangent(lIndex, 30);
lCurve->KeySetRightBezierTangent(lIndex, 30);
//You can use FBFCurveKey, but the performance will be much slower
//FBFCurveKey lKey = lCurve->Keys.GetAt(lIndex);
//lKey.TangentBreak = true;
//lKey.LeftBezierTangent = 30;
}
}
void ORTool_CustomTangent::EventKeyAddGeneric( HISender pSender, HKEvent pEvent )
{
FBCurveCustomKeyAddEvent lEvent(pEvent);
//index of the key that was added
int lIndex = lEvent.KeyIndex;
FBFCurve* lCurve = lEvent.Curve;
if(lCurve)
{
//since it was not a custom tangent, change that key for a custom type
//be sure to check if the curve belong to one of your object!
//you will also receive curves managed by Mobu, changing those keys will produce unexpected result!
FBAnimationNode* lParentNode = lEvent.GetParentAnimationNode();
VAR_NOT_USED( lParentNode );
FBComponent* lComponent = lEvent.GetParentComponent();
if(lComponent && lComponent->Is(FBModel::TypeInfo))
{
lCurve->KeySetInterpolation(lIndex, kFBInterpolationCustom);
lCurve->KeySetTangentCustomIndex(lIndex, kFBTangentCustomIndex1);
}
}
}
void ORTool_CustomTangent::EventKeyChange( HISender pSender, HKEvent pEvent )
{
FBCurveCustomKeyChangeEvent lEvent(pEvent);
//index of the key that was modified
int lIndex = lEvent.KeyIndex;
int lKeyBeforeIndex = lIndex -1;
int lKeyAfterIndex = lIndex + 1;
FBFCurve* lCurve = lEvent.Curve;
if(lCurve)
{
if(lCurve->Keys.GetCount() > lKeyAfterIndex)
{
//adjust settings based on the next key if needed
}
if(lKeyBeforeIndex >= 0)
{
//adjust settings based on the previous key if needed
}
lCurve->KeySetLeftTangentWeight(lIndex, 30);
lCurve->KeySetRightTangentWeight(lIndex, 30);
lCurve->KeySetLeftBezierTangent(lIndex, 30);
lCurve->KeySetRightBezierTangent(lIndex, 30);
if(lEvent.IsPreCall)
{
//do something
if(lEvent.ChangeType == kFBInterpolationChange)
{
if(lCurve->KeyGetInterpolation(lIndex) != kFBInterpolationCustom)
{
//moving from standard interpolation to custom!
//take a snapshot of the key if needed
}
}
else if(lEvent.ChangeType == kFBCustomTangentChange)
{
//changing from one custom type to another one
//kFBTangentCustomIndex0 -> kFBTangentCustomIndex1 for example
}
}
else
{
//do something
if(lEvent.ChangeType == kFBInterpolationChange)
{
//interpolation was changed...
}
}
//You can use FBFCurveKey, but the performance will be much slower
//FBFCurveKey lKey = lCurve->Keys.GetAt(lIndex);
//lKey.TangentBreak = true;
//lKey.LeftBezierTangent = 30;
}
}