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
    • Register
    • Login

    Get Selected Keyframes?

    Cinema 4D SDK
    2023 2024 python
    2
    6
    878
    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.
    • B
      bentraje
      last edited by

      Hi,

      Is there now an API in getting the selected keyframe?
      Much like doc.GetActiveObjects or doc.GetActiveMaterials

      My end goal operation is change the tangent handles (in the graph editor) of the selected kefyrames.
      The closest solution is in this thead (https://developers.maxon.net/forum/topic/10989/how-to-get-the-selected-keyframes-in-active-timeline-fcurve-manager/7)
      But it doesn't work on the latest versions of Cinema4D (even if you changed it to Python 3 syntax).

      Is there a way around this?

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

        Hello @bentraje,

        Thank you for reaching out to us. There always has been a means to retrieve the selection states of keyframes, namely the bit flags NBIT_TL1_SELECT, ..., NBIT_TL4_SELECT. There are no plans to extend this with convenance methods, as this is just fine as is. On c4d.BaseList2D there are some keyframe selection convenance methods, but they are very specialized and probably not too useful for the average Python user.

        There is also a slight bump in the road here, namely that a CKey is a C4DAtom and a GeListNode, but not a BaseList2D, which is a quite uncommon thing. This throws a wrench into the usual way of determining a selection state, BaseList2D.GetBit(c4d.BIT_ACTIVE). The reason is that there can be up to four dope sheet timeline editors active at once, which each can have its own selection state. Therefore there are four answers to the question "is this keyframe selected in a dopesheet editor?".

        Find a simple example attached below.

        Cheers,
        Ferdinand

        Result:
        41018394-9a28-4e8d-b3ea-3c658ad1f34f-image.png

        Code:

        """Prints out the selection state of keyframes for the currently selected object.
        
        Because there can be up to four timelines which do not share a selection state, there are four 
        answers to the question "is this keyframe selected?".
        """
        import c4d
        
        doc: c4d.documents.BaseDocument  # The currently active document.
        op: c4d.BaseObject | None  # The primary selected object in `doc`. Can be `None`.
        
        def main() -> None:
            """Called by Cinema 4D when the script is being executed.
            """
            if not op:
                return
            
            # Iterate over all tracks of the active object.
            track: c4d.CTrack
            for track in op.GetCTracks():
                curve: c4d.CCurve = track.GetCurve()
                # Iterate over all keys of the curve of this track.
                for i in range(curve.GetKeyCount()):
                    key: c4d.CKey = curve.GetKey(i)
                    # Check if the key #i is selected in any of the up to four timeline editors.
                    for n in (c4d.NBIT_TL1_SELECT, 
                              c4d.NBIT_TL2_SELECT, 
                              c4d.NBIT_TL3_SELECT, 
                              c4d.NBIT_TL4_SELECT):
                        isSelected: bool = key.GetNBit(n)
                        if isSelected:
                            # NBIT_TL1_SELECT has the value 5, NBIT_TL2_SELECT 6, etc.
                            print (f"The key {key} in the track {track} is selected in the timeline '{n - 4}'.")
        
        if __name__ == '__main__':
            main()
        
        

        MAXON SDK Specialist
        developers.maxon.net

        1 Reply Last reply Reply Quote 1
        • B
          bentraje
          last edited by

          @ferdinand

          Thanks for the response. This is probably the info I missed out:
          CKey is a C4DAtom and a GeListNode, but not a BaseList2D, which is a quite uncommon thing

          I tried your code but I'm not sure if its a bug.
          If I select a key in the timeline (dope sheet mode). It works.
          But if I select a key in the timeline (fcurve sheet mode). It doesn't.
          (It spits out a value but the value it spits out is the last selected key in dopesheet and not the actively selected key in fcurve)

          So I'm guessing I need to replace NBIT_TL1_SELECT with NBIT_TL1_FCSELECT but it still doesn't work.

          Am I missing something?

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

            The NBITs you are looking for are NBIT_TL1_SELECT2 ... NBIT_TL4_SELECT2.

            MAXON SDK Specialist
            developers.maxon.net

            1 Reply Last reply Reply Quote 1
            • B
              bentraje
              last edited by

              @ferdinand

              Slr. I can confirm the "Select2" works as expected.
              Just want to point out though. That option is present in the documentation but doesn't have a proper description (?).
              It's set to Private.

              https://developers.maxon.net/docs/py/2024_2_0/consts/NBIT.html?highlight=nbit_tl1_select

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

                Hey @bentraje,

                yes, we are aware that internal and private tags are something that plagues our documentation as they often have been abused by developers to skip documentation. But that is not so easy to fix.

                I for example did and still do not know the purpose NBIT_TLX_SELECT2 either. I was just experienced enough with the C4D API to poke in this place first.

                Physically fixing the docs, i.e., adding a blab here or there, is not the problem. The problem is to evaluate if the private tag in C++ (which then radiates into Python) is well founded or not, especially for ancient things like this. I would have to read a lot of code to make an assessment if this should be private or not, and even then would not be sure. And even an 'Expresses the selection state of f-curve keys. @markprivate' is problematic because for that I would have to be sure that it does not have a weird side effect.

                Cheers,
                Ferdinand

                MAXON SDK Specialist
                developers.maxon.net

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