Search code examples
pythonpython-2.73dsmax

How to create a keyframe with Python API for 3D Studio Max


Currrently I'm creating keyframes with autokey, like this:

MaxPlus.Animation.SetAnimateButtonState(True)  # autokey on
MaxPlus.Animation.SetTime(time)                # Set time slider to chosen time of keframe
obj.Position = MaxPlus.Point3(x, y, z)         # Set position
MaxPlus.Animation.SetAnimateButtonState(False) # autokey off

But this is not really convinient. Is there any other way? Is there a function like: createKeyframe(time, value)? How to access visibility controller?

I should probbably use:

c = MaxPlus.Factory.CreateDefaultFloatController()
obj.ParameterBlock.Parameter.SetController(c) 

But still I do not know how to insert keyframes and I only know how to set them with AutoKey, so this changes nothing


Solution

  • With max 2016, there's hardly a better way than what you're doing. Sure, you can assign a new visibility controller:

    node.SetVisibilityController(MaxPlus.Factory.CreateDefaultFloatController())
    

    Or you can modify any existing one:

    node.GetSubAnim(0).AddNewKey(time, param)
    

    where param is a sum of any of

    MaxPlus.Constants.AddkeyFlagged
    MaxPlus.Constants.AddkeyInterp
    MaxPlus.Constants.AddkeySelect
    

    but to work with the values of the keys, you have to get the IKeyControl/ISetKeyControl interface. This won't work:

    ctrl.GetInterface(MaxPlus.AnimatableInterfaceIds.IKeycontrol)
    

    as it expects MaxPlus.Interface_ID type and IKeycontrol (which stands for the original I_KEYCONTROL here) is instead a const of value 0x00001100. However, the original implementation goes something like:

    void* Control::GetInterface(ULONG id)
    {
        if (id==I_CONTROL) {
            return this;
        }
        else if (id==I_KEYCONTROL) {
            ...;
        }
        // and so on, only as a last resort checking the Interface_ID
        else {
            return Animatable::GetInterface(id);
        }
    }