Solved CCurve.FindPrevUnmuted & CCurve.FindNextUnmuted

I am trying to use CCurve.FindPrevUnmuted & CCurve.FindNextUnmuted. In this example based on @m_magalhaes CreateKey demo, I'm passing the middle key's index to these respective methods. Both return the middle key which is unexpected. Based on the documentation, FindPrevUnmuted should return the previous unmuted key and FindNextUnmuted should return the next unmuted key using the index parameter as the starting index. Am I using this incorrectly or is something else going wrong? Thank you!

import c4d

def CreateKey(curve, time, value, interpolation):
    keyDict = curve.AddKey(time)
    if keyDict is None:
        raise MemoryError("Failed to create a key")

    key = keyDict["key"]
    keyIndex = keyDict["nidx"]
    key.SetValue(curve, value)
    curve.SetKeyDefault(doc, keyIndex)
    key.SetInterpolation(curve, interpolation)
    return key, keyIndex

def main():
    obj = c4d.BaseObject(c4d.Ocube)
    trackY = c4d.CTrack(obj, c4d.DescID(c4d.DescLevel(c4d.ID_BASEOBJECT_POSITION, c4d.DTYPE_VECTOR, 0),
                                        c4d.DescLevel(c4d.VECTOR_Y, c4d.DTYPE_REAL, 0)))
    curveY = trackY.GetCurve()

    keyA, keyAIndex = CreateKey(curveY, c4d.BaseTime(0), value=0, interpolation=c4d.CINTERPOLATION_SPLINE)

    keyBTime = c4d.BaseTime(10, doc.GetFps())
    keyB, keyBIndex = CreateKey(curveY, keyBTime, value=100, interpolation=c4d.CINTERPOLATION_SPLINE)

    bt = c4d.BaseTime(5, doc.GetFps())
    keyDict = curveY.AddKeyAdaptTangent(bt, True, True)

    # -------------- #
    prevKey = curveY.FindPrevUnmuted(keyDict["nidx"])
    nextKey = curveY.FindNextUnmuted(keyDict["nidx"])

    print("prevKey index:",prevKey[1],", prevKey value:",prevKey[0].GetValue()) #returns keyDict's values
    print("nextKey index:",nextKey[1],", nextKey value:",nextKey[0].GetValue()) #returns keyDict's values 
    # -------------- #


if __name__ == '__main__':

Hi @blastframe,

thank you for reaching out to us. And again you are right, the documentation is here unfortunately also not the greatest. As a somewhat immediate fix, you could do this:

prevKey = curveY.FindPrevUnmuted(keyDict["nidx"] - 1)
nextKey = curveY.FindNextUnmuted(keyDict["nidx"] + 1)

I.e., you cannot include in the key index of the key you want to search from, because the logic here will be otherwise: "Well, the next/prev unmuted key to the passed key is the key itself, since it is a unmuted one). Which is being reflected in the argument description:

index (int) – The key index to start the search from: 0 <= idx < GetKeyCount()

but does not mesh very well with the method name. We are also going to fix also the documentation on this one (here including C++). And just for clarity, you can always iterate over the keys of a CCurve , i.e., just access them by their index:

for eid in range(curveY.GetKeyCount()):
    key = curveY.GetKey(eid)
    print(eid, key)

I am sorry, I understand your CCurve documentation experience was probably not the greatest, but we try to improve.

Thank you for your understanding,

MAXON SDK Specialist

@ferdinand Thank you for this; it makes things much clearer. I am very grateful we have the forum to clarify these issues.