Get selected keyframe in f-curve editor

On 06/04/2017 at 07:47, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   R17 
Platform:   Windows  ;   
Language(s) :       PYTHON  ;

---------
Hey there,

for my plugin I need to know which keyframe and or fcurve has been selected.

I know of checking key via GetNBit, running the following code in a loop returns 0 for every single bit when selecting a curve or key in the f-curve timeline.
If I select keys in dopesheet-mode c4d.NBIT_TLx_SELECT returns the right values

print ("------------------ SEL BITS KEY ---------------")  
print str(key.GetNBit(c4d.NBIT_TL1_SELECT))  
print str(key.GetNBit(c4d.NBIT_TL2_SELECT))  
print str(key.GetNBit(c4d.NBIT_TL3_SELECT))  
print str(key.GetNBit(c4d.NBIT_TL4_SELECT))  
print ("------------------ SEL BITS CURVE ---------------")  
  
print str(curve.GetNBit(c4d.NBIT_TL1_FCSELECT))  
print str(curve.GetNBit(c4d.NBIT_TL2_FCSELECT))  
print str(curve.GetNBit(c4d.NBIT_TL3_FCSELECT))  
print str(curve.GetNBit(c4d.NBIT_TL4_FCSELECT))  
print ("------------------ SEL BITS END -----------------")

I can act on any curve or keys that get I try this part of the code, so there shouldnt be a problem there.

Am I using this feature wrong or is there a bug with the NBits? Is there any other way to find out if a key got selected in the f-curve editor?

On 06/04/2017 at 08:13, xxxxxxxx wrote:

Hello and welcome unti have a look at this thread
https://plugincafe.maxon.net/topic/5517/5536_selected-keys-move-keys
Basicly you have to check c4d.BIT_ACTIVE

Moreover I know it's a bit stupid but SDK forum is for C++ while in your case you must use Python category.

On 06/04/2017 at 08:38, xxxxxxxx wrote:

Hey, thanks for the quick reply. I already found that thread.

Sadly, this doesn't work as CKey does not inherit from BaseList2D which provides the GetBit functionality.

Beeing thorough, I already tested getBit() and check for active in code which doesn't work.

Oh, ok..  I put this post into the general sdkHelp as it seems to be the same case with the c++ api

On 06/04/2017 at 10:23, xxxxxxxx wrote:

Hoo yes you are right I can't either get the selection in Fcurves mode

On 06/04/2017 at 11:13, xxxxxxxx wrote:

I think this is what you're look for

import c4d  
def main() :  
  
  obj = doc.GetActiveObject()  
  if obj is None: return False      
    
  trk = obj.GetFirstCTrack()  
  if trk is None: return False      
    
  curve = trk.GetCurve()  
  key = curve.GetKey(0)      #The first key on the track (change as desired)  
  selected = key.GetNBit(5)  #5 is the ID for the animation layout's timeline GUI  
    
  if selected == True:  
      print key.GetValue()  
  c4d.EventAdd(c4d.MSG_UPDATE)   
  
if __name__=='__main__':  
  main()

-ScottA

On 07/04/2017 at 00:12, xxxxxxxx wrote:

Hey Scott, thanks for your answer.

Basically key.GetNBit(5) is the same as key.GetNBit(c4d.NBIT_TL1_SELECT) which works in dopesheet mode but doesn't in f-curve mode, like indicated in my first question. Dopesheetmode is not a workaround for my intended function, so if anyone could shed some light on that, it would be great. Also, if this is a bug in R17 that has been fixed in R18, let me know.

Other than that your code is perfect for testing my snippet and see if any NBIT returns 1 in cinema without reloading my plugin :) Thanks for that.

On 07/04/2017 at 05:18, xxxxxxxx wrote:

Hi,

sorry for being late to the party.
So, there are these four private bits: NBIT_TL1_SELECT2 to NBIT_TL4_SELECT2
I talked to our development and you may use them read-only. So you may detect if a key is selected in F-Curve mode. Please do not try to change the selection with these. It might have unexpected consequences and you have been warned! I know, I say something like this sometimes with a wink, but not this time. I really mean it, please use it for reading, only. In the end no one will benefit if customer's projects get destroyed, right?

On 07/04/2017 at 06:42, xxxxxxxx wrote:

So what is the utility of the NBIT_TL1_FCSELECT?
In case we want to make a selection on the fcruve. Does Set NBIT_TL1_SELECT will automaticly set NBIT_TL1_SELECT2 ? And the most important is it safe?

On 07/04/2017 at 09:32, xxxxxxxx wrote:

Hey, thanks a lot, NBIT_TLx_SELECT2 did the job perfectly.

Find attached a 'fixed' version of Scotts code:
This code only checks the very first key it can find, to use it to detect more than that you will have to run it in a loop. I might whip up a short example for everyone else next week.
Thanks again.

Just to dig a little deeper, is there an API even when a key gets selected? - But this is just for optimization purposes, so dont bother if its to complicated.

I can't seem to mark this post as solved, so if any admin would do that it would be great :)

import c4d  
def main() :  
  
  obj = doc.GetActiveObject()  
  if obj is None: return False      
    
  trk = obj.GetFirstCTrack()  
  if trk is None: return False      
    
  curve = trk.GetCurve()  
  key = curve.GetKey(0)      #The first key on the track (change as desired)  
  selected = key.GetNBit(NBIT_TL1_SELECT2)  #5 is the ID for the animation layout's timeline GUI  
    
  if selected == True:  
      print key.GetValue()  
  c4d.EventAdd(c4d.MSG_UPDATE)   
  
if \__name\_\_=='\__main\_\_':  
  main()  

On 07/04/2017 at 09:32, xxxxxxxx wrote:

Sorry about the unti. I wasn't really sure what you were asking for since there is no "dope sheet" mode in C4D. Only key mode & f-curve modes.

@gr4ph0s,
The NBIT_TL1_SELECT bit does not select the keys.
I've used it several times myself, and so far it seems to be safe with no issues.
Example:

import c4d  
def main() :  
  
  obj = doc.GetActiveObject()  
  if obj is None: return False      
    
  trk = obj.GetFirstCTrack()  
  if trk is None: return False      
    
  curve = trk.GetCurve()  
  key = curve.GetKey(0)      #The first key on the track (change as desired)  
  
  #Do this code block only if we are in F-Curve mode  
  if c4d.IsCommandChecked(465001190) :  
        
      #Selects the track's curve...but not the curve's keys  
      trk.ChangeNBit(c4d.NBIT_TL1_FCSELECT, c4d.NBITCONTROL_SET)  
      print trk.GetNBit(c4d.NBIT_TL1_FCSELECT)  
        
      trk.ChangeNBit(c4d.NBIT_TL1_FCSELECT, c4d.NBITCONTROL_CLEAR)  #un-selects the curve  
      print trk.GetNBit(c4d.NBIT_TL1_FCSELECT)  
   
  c4d.EventAdd(c4d.MSG_UPDATE)   
  
if __name__=='__main__':  
  main()

-ScottA