Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Creating a Keyframe similar to Ctrl-Clicking the Curve

    Cinema 4D SDK
    r23 windows python
    2
    3
    367
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • ?
      A Former User
      last edited by

      Hello,
      When in the Timeline, if I hold Ctrl/Cmd and click on the curve, Cinema 4D adds a keyframe that matches the contour of the curve perfectly.
      Curve2.jpg

      The tangents of the new key and neighboring keys are properly weighted.

      When I try to do this with the code below, I get a keyframe whose angles do not match the curve and where the Left & Right times of the neighboring keys are not adjusted.

      keyDict = keyCurve.AddKey(keyTime)
      keyIndex = keyDict["nidx"]
      key = keyDict["key"]
      key.SetValue(keyCurve,value)
      key[c4d.ID_CKEY_PRESET] = c4d.ID_CKEY_PRESET_NEWAUTOWEIGHTED
      

      Result:
      10972325-56f5-40c8-b50f-b32d3025c6bd-image.png

      The tangents of the key seem to be weighted properly using ID_CKEY_PRESET_NEWAUTOWEIGHTED, but how can I get the angle of the tangents to match the curve and the Left & Right Time of the neighboring keys to adjust so the curve's contour doesn't change as in the Ctrl-Click key creation scenario?

      Thank you!

      1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand
        last edited by

        Hi @blastframe,

        thank you for reaching out to us. One built in solution you could use is CCurve.AddKeyAdaptTangent() instead of CCurve.AddKey(). It will allow you to insert a smoothly interpolated key between two other keys and the result will look something like the attached image. I also attached a modified github ctrack_create_keys_r13.py example at the end. You only have to read the snip parts, everything else is unchanged.

        2798b905-ec91-4bc1-8363-ad0d65577044-image.png

        I hope this helps, if not, I would have to ask you to restate your goals.

        Cheers,
        Ferdinand

        """
        Copyright: MAXON Computer GmbH
        Author: Manuel MAGALHAES
        Description:
            - Creates position Y tracks.
            - Adds two keyframes.
            - Sets their value and interpolation.
        Class/method highlighted:
            - CKey.SetInterpolation()
            - CKey.SetKeyDefault()
        Compatible:
            - Win / Mac
            - R13, R14 R15, R16, R17, R18, R19, R20, R21, S22, R23
        """
        
        import c4d
        
        
        def CreateKey(curve, time, value, interpolation):
            """
            Creates a Key on the given curve at the given time with a given value and with the given interpolation.
            :param curve: The Curve where to add the keyframe.
            :type curve: c4d.CCurve
            :param time: The time of the keyframe.
            :type time: c4d.BaseTime
            :param value: The value of the keyframe.
            :type value: float
            :param interpolation: The interpolation of the key along the curve.
            :type interpolation: c4d.CINTERPOLATION_XXX
            :return: They key and the index of the key in the CCurve.
            :rtype: tuple(c4d.Ckey, int)
            :raise MemoryError: If for some reason, it was not possible to create the key.
            """
            # Adds the key
            keyDict = curve.AddKey(time)
        
            # Checks if the key have been added
            if keyDict is None:
                raise MemoryError("Failed to create a key")
        
            # Retrieves the inserted key
            key = keyDict["key"]
            keyIndex = keyDict["nidx"]
        
            # Sets the value of the key
            key.SetValue(curve, value)
        
            # Mandatory: Fill the key with default settings
            curve.SetKeyDefault(doc, keyIndex)
        
            # Changes it's interpolation
            key.SetInterpolation(curve, interpolation)
        
            return key, keyIndex
        
        
        def main():
            # Creates the object in memory
            obj = c4d.BaseObject(c4d.Ocube)
        
            # Creates the track in memory. Defined by it's DescID
            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)))
        
            # Gets curves for the track
            curveY = trackY.GetCurve()
        
            # Creates a key in the Y curve with value 0 at 0 frame with a spline interpolation
            keyA, keyAIndex = CreateKey(curveY, c4d.BaseTime(0), value=0, interpolation=c4d.CINTERPOLATION_SPLINE)
        
            # Retrieves time at frame 10
            keyBTime = c4d.BaseTime(10, doc.GetFps())
        
            # Creates another key in the Y curve with value 100 at 10 frame with a spline interpolation
            keyB, keyBIndex = CreateKey(curveY, keyBTime, value=100, interpolation=c4d.CINTERPOLATION_SPLINE)
            
            # --- snip ---
            
            # Add key in between the keys A and B.
            bt = c4d.BaseTime(5, doc.GetFps())
            curveY.AddKeyAdaptTangent(bt, True, True)
            
            # --- snip ---
        
            # Inserts the track containing the Y curve to the object
            obj.InsertTrackSorted(trackY)
        
            # Inserts the object in document
            doc.InsertObject(obj)
        
            # Pushes an update event to Cinema 4D
            c4d.EventAdd()
        
        
        # Execute main()
        if __name__ == '__main__':
            main()

        MAXON SDK Specialist
        developers.maxon.net

        ? 1 Reply Last reply Reply Quote 1
        • ?
          A Former User @ferdinand
          last edited by

          @ferdinand That was exactly what I was seeking, thank you, Ferdinand! 😄

          1 Reply Last reply Reply Quote 0
          • First post
            Last post