Solved Updating key timing creates incorrect fcurves. How do I do this properly?

Hello there!

First time posting here. I think I am posting properly but if I am not I apologize and will gladly update it. I have checked the docs and forums quite a bit regarding this and not yet found a solution.

I am working on a plugin that does a lot of nice utility functions and part of it is a set of animation tools. I am working on the reverse keys function and I am able to reverse the keys quite easily however when I reverse the keys the fcurves move with them instead of shifting. When I move the keys they update but I'm not sure what I am doing wrong here.

I assume I am probably approaching this the wrong way. I'm a bit newer to the C4D python SDK.

Cinema_4D_z6Vw8RxJl1.gif

Here is the code I have to complete this setup.

def reverseKeys(self):
        # Reverse timing of selected keys 
        keys = AnimationCommands().getSelectedKeys()[0]
        curves = AnimationCommands().getSelectedKeys()[2]

        keyFrameList = {}
        keyTimeList = {}

        # build keyframe timing list
        count = len(keys)
        i = 0
        while i < count:
            key = keys[i]
            keyTime = key.GetTime()
            keyTimeList[i] = keyTime
            keyFrame = keyTime.GetFrame(c4d.documents.GetActiveDocument().GetFps())
            keyFrameList[i] = keyFrame
            i += 1
        
        # get min and max timing values
        minKey = min(keyTimeList, key=keyTimeList.get)
        maxKey = max(keyTimeList, key=keyTimeList.get)
        minVal = keyTimeList[minKey]
        maxVal = keyTimeList[maxKey]
        range = maxVal - minVal
        #get distance per key from the first key
        #set that distance as the distance from the final key
        i2 = 0
        while i2 < count:
            ikey = keys[i2]
            keyCurve = curves[i2]
            keyOffset = keyTimeList[i2] - minVal
            newKeyTime = maxVal - keyOffset
            ikey.SetTime(keyCurve, newKeyTime)
            i2 += 1

And the code calling this function is this:

if id == GUI_ID["REVERSE_KEYS"]:
            AnimationCommands().reverseKeys()
            c4d.DrawViews(c4d.DRAWFLAGS_NO_THREAD | c4d.DRAWFLAGS_FORCEFULLREDRAW)
            c4d.GeSyncMessage(c4d.EVMSG_CHANGE)

Some lines in here may be useless and redundant. I'm honestly not certain. For example the DrawViews command was something I put in to see what it did to my updates. I noticed nothing.

Thank you in advance for the help! The forums have been tremendously helpful in learning how to work with the SDK.

Best regards,
Sam

hi,

welcome to the forum and thanks for reaching us out. Thanks for the question and the clarity of it.

The issue here is that you are changing the Time value of the keys but not their indexes.
One function that could help you is SortKeysByTime but as you can see, it is marked as private. I am not sure why it is marked private here. There might have some cases where this function will not give you the correct result. you could create your own algorithm to sort those keys.

Another solution could be to delete those keys and re-insert them, they will be sorted as you insert them.

Cheers,
Manuel

MAXON SDK Specialist

MAXON Registered Developer

hi,

welcome to the forum and thanks for reaching us out. Thanks for the question and the clarity of it.

The issue here is that you are changing the Time value of the keys but not their indexes.
One function that could help you is SortKeysByTime but as you can see, it is marked as private. I am not sure why it is marked private here. There might have some cases where this function will not give you the correct result. you could create your own algorithm to sort those keys.

Another solution could be to delete those keys and re-insert them, they will be sorted as you insert them.

Cheers,
Manuel

MAXON SDK Specialist

MAXON Registered Developer