How we can access keyframes of a controller to change outtangenttype and intangenttype?
Set tangents type (C#)
in c++ we would do something like this…
Control *ctrl= node->GetTMController()->GetPositionController();
IKeyControl* keys = GetKeyControlInterface(ctrl);
int numkeys = keys->GetNumKeys();
// if bezier controller
IBezPoint3Key kf;
keys->GetKey(i,&kf);
// tweak
kf.outtan = Point3(1,0,0);
keys->SetKey(i,&kf);
you’ll have to translate it into c#
// istdplug.h
#define BEZKEY_SMOOTH 0
#define BEZKEY_LINEAR 1
#define BEZKEY_STEP 2
#define BEZKEY_FAST 3
#define BEZKEY_SLOW 4
#define BEZKEY_USER 5
#define BEZKEY_FLAT 6
// wm3_channel.cpp
void morphChannel::SetUpNewController()
{
int in, out;
GetBezierDefaultTangentType(in, out);
SetBezierDefaultTangentType(BEZKEY_STEP, BEZKEY_STEP);
Control *c = (Control*)CreateInstance(CTRL_FLOAT_CLASS_ID,GetDefaultController(CTRL_FLOAT_CLASS_ID)->ClassID());
cblock->SetValue(0,0,0.0f);
cblock->SetController(0,c);
SetBezierDefaultTangentType(in, out);
}
this is probably what you need.
found it in sdk files in a second using grepWin
No , I don’t want to change the global default tangent type. I just want to change all tangents of a controller.
they are stored as flags in the IKey::flags data member…
#define BEZKEY_SMOOTH 0
#define BEZKEY_LINEAR 1
#define BEZKEY_STEP 2
#define BEZKEY_FAST 3
#define BEZKEY_SLOW 4
#define BEZKEY_USER 5
#define BEZKEY_FLAT 6
#define NUM_TANGENTTYPES 7
#define BEZKEY_NUMTYPEBITS 3
#define BEZKEY_INTYPESHIFT 7
#define BEZKEY_OUTTYPESHIFT (BEZKEY_INTYPESHIFT+BEZKEY_NUMTYPEBITS)
#define BEZKEY_TYPEMASK 7
#define GetInTanType(f) int(((f)>>BEZKEY_INTYPESHIFT)&BEZKEY_TYPEMASK)
#define GetOutTanType(f) int(((f)>>BEZKEY_OUTTYPESHIFT)&BEZKEY_TYPEMASK)
#define SetInTanType(f, t) {(f) = ((f)&(~(BEZKEY_TYPEMASK<<BEZKEY_INTYPESHIFT)))|(t<<BEZKEY_INTYPESHIFT);}
#define SetOutTanType(f, t) {(f) = ((f)&(~(BEZKEY_TYPEMASK<<BEZKEY_OUTTYPESHIFT)))|(t<<BEZKEY_OUTTYPESHIFT);}
where f is the flags data member and t is the type
so in the previous example i posted it would be…
IBezPoint3Key kf;
keys->GetKey(i,&kf);
SetInTanType(kf.flags, BEZKEY_STEP );
SetOutTanType(kf.flags, BEZKEY_STEP );
there’s actually nothing much complicated
try to use it as an example
c# sdk
public static bool SetControllerTangentType( int anim_handle )
{
// todo: DISPOSE
IAnimatable anim = global.Animatable.GetAnimByHandle( new UIntPtr( (uint)anim_handle ) );
IControl ctrl = (IControl)anim;
IIKeyControl keys = (IIKeyControl)(ctrl.GetInterface( InterfaceID.Keycontrol ));
if ( keys == null ) return false;
IIBezFloatKey kf = global.IBezFloatKey.Create();
keys.GetKey( 0, kf );
uint BEZKEY_STEP = 2;
// ...
// ...
uint BEZKEY_NUMTYPEBITS = 3;
int BEZKEY_INTYPESHIFT = 7;
int BEZKEY_OUTTYPESHIFT = (int)(BEZKEY_INTYPESHIFT + BEZKEY_NUMTYPEBITS);
uint BEZKEY_TYPEMASK = 7;
// #define SetInTanType(f, t) {(f) = ((f)&(~(BEZKEY_TYPEMASK<<BEZKEY_INTYPESHIFT)))|(t<<BEZKEY_INTYPESHIFT);}
kf.Flags = (kf.Flags & (~(BEZKEY_TYPEMASK << BEZKEY_INTYPESHIFT))) | (BEZKEY_STEP << BEZKEY_INTYPESHIFT);
// #define SetOutTanType(f, t) {(f) = ((f)&(~(BEZKEY_TYPEMASK<<BEZKEY_OUTTYPESHIFT)))|(t<<BEZKEY_OUTTYPESHIFT);}
kf.Flags = (kf.Flags & (~(BEZKEY_TYPEMASK << BEZKEY_OUTTYPESHIFT))) | (BEZKEY_STEP << BEZKEY_OUTTYPESHIFT);
keys.SetKey( 0, kf );
return true;
}
mxs test script
b = bezier_float()
animate on
(
at time 0 b.value = 10
at time 20 b.value = 20
)
handle = getHandleByAnim b
SetControllerTangentType handle
c = Cylinder()
c.height.controller = b
ant don’t forget to dispose anything that can be disposed otherwise it will surely leak
I little organized the code:
using Autodesk.Max;
using System;
namespace Library
{
public static class ControllerHelper
{
static IGlobal globalInterface = GlobalInterface.Instance;
public static class TangentType
{
public static uint Smooth = 0, Linear = 1, Step = 2, Fast = 3, Slow = 4, User = 5, Flat = 6;
}
const uint NUM_TANGENTTYPES = 7;
const uint BEZKEY_NUMTYPEBITS = 3;
const int BEZKEY_INTYPESHIFT = 7;
const int BEZKEY_OUTTYPESHIFT = (int)(BEZKEY_INTYPESHIFT + BEZKEY_NUMTYPEBITS);
const uint BEZKEY_TYPEMASK = 7;
public static int GetInTanType(uint f)
{
return (int)((f >> BEZKEY_INTYPESHIFT) & BEZKEY_TYPEMASK);
}
public static int GetOutTanType(uint f)
{
return (int)((f >> BEZKEY_OUTTYPESHIFT) & BEZKEY_TYPEMASK);
}
public static void SetInTanType(ref IIBezFloatKey key, uint t)
{
key.Flags = (key.Flags & (~(BEZKEY_TYPEMASK << BEZKEY_INTYPESHIFT))) | (t << BEZKEY_INTYPESHIFT);
}
public static void SetOutTanType(ref IIBezFloatKey key, uint t)
{
key.Flags = (key.Flags & (~(BEZKEY_TYPEMASK << BEZKEY_OUTTYPESHIFT))) | (t << BEZKEY_OUTTYPESHIFT);
}
public static bool StepAllKeys(int control_handle)
{
IControl control = (IControl)globalInterface.Animatable.GetAnimByHandle(new UIntPtr((uint)control_handle));
IIKeyControl keyControl = (IIKeyControl)(control.GetInterface(InterfaceID.Keycontrol));
if (keyControl == null) return false;
IIBezFloatKey key = globalInterface.IBezFloatKey.Create();
for (var i = 0; i < keyControl.NumKeys; i++)
{
keyControl.GetKey(i, key);
SetInTanType(ref key, TangentType.Step);
SetOutTanType(ref key, TangentType.Step);
keyControl.SetKey(i, key);
}
control.Dispose();
keyControl.Dispose();
key.Dispose();
return true;
}
}
}
All we did are based on your code, Thank You my master!
I’m not native English speaker and sometimes I’m not sure I understand your meaning. For example “ignore me” doesn’t makes sense for me in this case.
i just edit an irrelevant post about checking the class ID to make sure the control was a bezier type.
