set keys via script ?

Become a member of the CGSociety

Connect, Share, and Learn with our Large Growing CG Art Community. It's Free!

Thread Tools Display Modes
  12 December 2010
set keys via script ?


in my timeline a have a curve selected with two keyframes, one at 0 and one at 75.
Now i want to 'subdivide' the curve by inserting new keys at 15,25,35,45,55,65.

Is this possible via a script in R11.5 ?

I started the script, but i dont know how to get the currently active CCurve, and add the new keys.
Is this possible with COFFEE ?

Here's what i got so far:

         var fps = doc->GetFps();
         var TimeNow = doc->GetTime();
         var currFrame = TimeNow->GetFrame(fps);
         var keyCount = 6;
         var keyArr = new(array,6);
         keyArr[0] = 15;
         keyArr[1] = 25;
         keyArr[2] = 35;
         keyArr[3] = 45;
         keyArr[4] = 55;
         keyArr[5] = 65;
         var k=0;
             if(!doc->SetTime(TimeNow)) break;
             else println("jumped to frame ",keyArr[k]);
    	  // add a frame at current position to currently selected CCurve
         // go back to initial frame
         println("returned to frame ",currFrame);

  12 December 2010
I think in coffee you can only manipulate existing keys, not create new ones. You may have to do a workaround by pressing the set key button with coffee code. Sorry I can't help you more, I never quite got coffee before I changed to Python.
Cinema 4D R19 Studio, Octane, Z Brush, Mudbox, Adobe CC
  12 December 2010
We can't create keys with Coffee. It's one of the things we've all been complaining about for many years.
It would be very nice to be able to pick a specific curve, and a specific frame, and then use some sort of a SetKey() function. But Maxon refuses to treat this as a priority.

The only way to create new keys is to use Coffee to move the scrubber to a specific location and then use the record option.
And because the record option is set up to set keys on all tracks on an object. You'll also have to worry about toggling the Position,Scale, and Rotation options on/off at the same time you're moving the scrubber around with the code so that you don't set unwanted keys on unwanted tracks.

You can use loops to iterate through the time line hierarchy to target specific curves, on specific tracks the same way you iterate through the object manager. But you'll still have to use the record key option to actually create a new key.
I have several examples for this kind of stuff in my Coffee Bible posted in the scripts section.

My Gallery
  12 December 2010
thanks for the info guys.

I think it should be possible then to do what i need.
Just go to the frame in question and then record keys for position.

Gonna check out the bible now, looks very handy indeed!

  12 December 2010
ok i got most of ot working, there's only one thing left to do.

Is it possible to pass parameters to this script from a userData slider ?
Right now the 'offset' var is hardcoded in the script, but actually it depends on some user data I have set up in my scene.

Here's the updated script, at Frames 5,15,25,35,45,55 and 65 it records a new key and sets interpolation mode to step, which is the main task i wanted it to handle.

    // set the input params
    var start = 5;
    var offset = 10;
    var end = 75;
    // Set Interpolation for all keys in given curve
    // 1=spline, 2=linear, 3=step
    	var i=0;
    	for(i=0; i<curve->GetKeyCount(); i++){ 
    // delete all keys on this curve
    // main routine 
    	println("--- running Script: Subdivide Pos-Tracks ---");
    	var op = doc->GetActiveObject();
    		println("no object selected!");
    	// setup some vars
    	var fps = doc->GetFps();
    	var TimeNow = doc->GetTime();
    	var currFrame = TimeNow->GetFrame(fps);
    	var track_x; var track_y; var track_z;
    	var curve_x; var curve_y; var curve_z;
    	var count_x; var count_y; var count_z;
    	// find x,y and tracks
    	var track = op->GetFirstCTrack();
    		if(track->GetName()=="Position . X") track_x = track;
    		else if(track->GetName()=="Position . Y") track_y = track;
    		else if(track->GetName()=="Position . Z") track_z = track;
    		track = track->GetNext();
    	// get curves and initial key count
    	if(track_x!=null) curve_x = track_x->GetCurve();
    	if(track_y!=null) curve_y = track_y->GetCurve();
    	if(track_z!=null) curve_z = track_z->GetCurve();
    	if(curve_x!=null) count_x = curve_x->GetKeyCount();
    	if(curve_y!=null) count_y = curve_y->GetKeyCount();
    	if(curve_z!=null) count_z = curve_z->GetKeyCount();
    	if((count_x+count_y+count_z)==0) return; // nothing to do!
    	//Turn off record rotation option if it's on
    	if(IsCommandChecked(12418)) CallCommand(12418);
    	//Turn off record scale option if its on
    	if(IsCommandChecked(12419)) CallCommand(12419);
    	// turn off record parameter keys, if its on
    	if(IsCommandChecked(12422)) CallCommand(12422);
    	// turn off record PLA if its on
    	if(IsCommandChecked(12421)) CallCommand(12421);
    	// scrub through time, where we want to set new keys
    	  if(!doc->SetTime(TimeNow)) break;
    		CallCommand(12410); 	// record a new key
    		start += offset;
    	// cleanup curves. if there were no keys before, we need not subdivide the curve
 	// if there were keys before and its subdivided now, set interpolation to step
    	if(count_x<1) deleteAllKeysOnCurve(curve_x);
 	else setInterpolationForCurve(curve_x,3);
    	if(count_y<1) deleteAllKeysOnCurve(curve_y);
 	else setInterpolationForCurve(curve_y,3);
    	if(count_z<1) deleteAllKeysOnCurve(curve_z);
    	else setInterpolationForCurve(curve_z,3);
    	// go back to initial frame

Last edited by bellaLugosi : 12 December 2010 at 08:03 AM. Reason: improved code
  12 December 2010
You can search for your object with your Userdata
either by name or criteria, such as the relative
position (in OM), Parent, Child etc.
Or simply make a Dialog in your script
to set the parameters.

To get the recording option(s) you want,
You use the IsCommandChecked() to get the current state,
then CallCommand() to toggle what you need.
The following i.e. will only set Parameters and PointLevel
to ON while running and then reset to the initial setup.


 var posOn   = IsCommandChecked(12417);  // Get State
 var scaleOn = IsCommandChecked(12418);  // Get State
 var rotOn   = IsCommandChecked(12419);  // Get State
 var parOn   = IsCommandChecked(12422);  // Get State
 var pointOn = IsCommandChecked(12421);  // Get State
  if(posOn)         CallCommand(12417);  // Position Temp Off
  if(scaleOn)       CallCommand(12418);  // Scale Temp Off
  if(rotOn)         CallCommand(12419);  // Rotation Temp Off
  if(!parOn)        CallCommand(12422);  // Parameter Temp On
  if(!pointOn)      CallCommand(12421);  // Point Level Animation Temp On

// Do Your thing

  if(posOn)    CallCommand(12417); // Position
  if(scaleOn)  CallCommand(12418); // Scale
  if(rotOn)    CallCommand(12419); // Rotation
  if(!parOn)   CallCommand(12422); // Parameter
  if(!pointOn) CallCommand(12421); // Point Level Animation
MSA | OSX | xfiles ...Cinema4D Tools
  12 December 2010
thanks for the info.
actually i think i messed with this before in the past, just cant remember atm ;-)

  12 December 2010
Just a side note about creating new keys.
Python has a couple of functions that supposedly create keys. But so far I've never seen it used in any scripts to see how to write it.
A few months ago me and Nitroman asked Sebastian for a small example on using it in his forum. But he never replied back to us.
So if you ever dive into Python in the future. It might be worth looking into.

I took another look at creating keys with python. And I managed to (sort of) figure it out on my own.
I guess that means I'm getting better at reading these cryptic SDK's. Sorta like how you can read your wife's handwriting after years of practice.

Here's a sample Python snippet in case anyone is interested:
#This script adds a blank key (zero) where the scrubber is on the timeline
#Then sets it value after it's been created

import c4d
from c4d import gui

def main():
	obj = doc.GetActiveObject() #Find the active object
	track = obj.GetFirstCTrack() #Get it's first animation track (position X) 
	if not track: return # if it doesn't have any tracks. End the script
	curve = track.GetCurve() #Get the curve for the track found(position x)
	time = doc.GetTime() #Gets the document time 
	frame = time.GetFrame(doc.GetFps()) #Get the frame the scrubber is on
  #Adds a new key for the first track. Where the scrubber is located
	added = curve.AddKey(time)# creates a new empty key where the scrubber is currerntly located
	curve.GetKey(2).SetValue(curve, 120) # Sets the value of the new key to this value
if __name__=='__main__':

My Gallery

Last edited by Scott Ayers : 12 December 2010 at 09:22 PM.
  12 December 2010
Thread automatically closed

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.
CGTalk Policy/Legalities
Note that as CGTalk Members, you agree to the terms and conditions of using this website.
Thread Closed share thread

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Society of Digital Artists

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump

All times are GMT. The time now is 12:01 PM.

Powered by vBulletin
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.