Posts Tagged ‘easy

21
Jan
12

FCurves Interpolation

Hi, for our next tool, we’ll learn how to change the interpolation style on FCurves. This can be really useful when you want to move from blocking to first pass, I use it all the time when working on shots. We’ll need to build a list of the transform parameters (if you’re wondering where you can find those or how to properly write them, just select any object in your scene and go through the sdk explorer View–Scripting–SDK Explorer / Ctrl+Shift+4, once there go into the Parameters section, find the parameters you want and look in the scriptname column). We’ll also need to lock the current selection so that no matter what we do, the script will remember which items were selected when we pressed the button, to do that we’ll use a tuple to store the list permanently (Application.Selection is dynamic, so the script could forget what was used in the beginning).

xsi = Application
parameters = ["posX", "posY", "posZ", "rotX", "rotY", "rotZ", "sclX", "sclY", "sclZ"]
selection = tuple(xsi.Selection)

Next, we’ll go through each of our selected items, loop through their parameters and check if they’re keyable. If they are we’ll grab their FCurves (if they exist) and change the interpolation type

1 = Constant (step)
2 = Linear
3 = Spline

for item in selection:
	for param in parameters:
		parameter = item.kinematics.local.Parameters(param)
		if parameter.Keyable:
			fcurve = parameter.Source
			if fcurve != None:
				fcurve.Interpolation = 1

Now, we could replicate the script and change the value and have one button for each type of interpolation OR, we could add a little trick to change the behavior of the button depending on what key (shift, ctrl, alt) the user is pressing when he clicks the button.

To be able to do that, you’ll need to know what is pressed and the way to do that is through the GetKeyboardState function. Look for it in the manual, experiment with it, try out different combos, have fun with it.

ks = xsi.GetKeyboardState()

shift = 1
ctrl = 2

if ks(1) == shift:
	interpolation = 1
elif ks(1) == ctrl:
	interpolation = 2
else:
	interpolation = 3

So in the end, our code could look something like this:

## This script switches the interpolation of the selected object's transformation FCurves.
## Hold Shift while running the script to switch the FCurves to constant
## Hold Ctrl while running the script to switch the FCurves to linear
## Hold anything else or nothing at all while running the script to switch the FCurves to spline

xsi = Application
parameters = ["posX", "posY", "posZ", "rotX", "rotY", "rotZ", "sclX", "sclY", "sclZ"]
selection = tuple(xsi.Selection)
ks = xsi.GetKeyboardState()

shift = 1
ctrl = 2

if ks(1) == shift:
	ipl = 1
elif ks(1) == ctrl:
	ipl = 2
else:
	ipl = 3

for item in selection:
	for param in parameters:
		parameter = item.kinematics.local.Parameters(param)
		if parameter.Keyable:
			fcurve = parameter.Source
			if fcurve != None:
				fcurve.Interpolation = ipl

In this example, the default interpolation will be Spline. If you run the script while pressing shift, it will switch the keys to constant interpolation, ctrl will switch it to linear, anything else (including nothing) will give you splines.

14
Jan
12

Keep Ref Keys

Hi! Sorry for the wait, long story short I broke my ankle and didn’t have access to my computer due to ergonomic issues.

I asked someone from work which tool I should start with, a simple one with not too many bells and whistles, a simple one button solution. As he suggested, I’ll start off with a simple tool that will keep the animation keys only on frames where a reference object has keys. I don’t personally use this tool a lot but it was requested by a lot of animators during my last project so I figure other people might find it interesting. At the very least it will teach you how to interact and manipulate keys and FCurves through scripting.

Now, let’s start with the basics. How to approach a problem like this? What will we need?

We’ll need a source object from which to get our frames to keep and we’ll need a target object that has a lot of keys that we want to clean up. We’ll also need to know how to access the frame number for each key and how to delete keys at specific frames. Since this will be a one button solution, let’s keep things simple. We’ll predetermine the order in which the objects need to be selected and go from there.

First, let’s write a small description of what the script will do and how to use it. It might seem like useless work now but if you ever need to revisit it later on, you’ll be glad you did. It also makes it easier to distribute it if it comes with it’s own instruction manual. We’ll also set up some variables that we’ll be using throughout the script

#
##  This script keeps only the keys on the target object for frames matching the source object's keyed frames
##  Instructions:
##     Select the target object you want to clean up
##     Select the object you want to use as a source
##     Run the script

##  -------------------------------------------------------------------------------------------------

from win32com.client import constants as c
xsi = Application
target = xsi.Selection(0)
source = xsi.Selection(1)

Now that these are setup they can be reused throughout the script easily. Next we’re going to create a list of keyed frames from the “source” object, which we will use as a reference for which keys to keep on the “target” object. The way to do this is to first create an empty list and then append the values to it as we go through each of the animatable parameters (in this case we’ll use only the transforms).

To get access to the frames where keys are stored, you need to first get the FCurves, from those you can then get the keys, and then from the keys you can isolate the “.Time” parameter which is actually the frame information. I usually round up the value at this point because in some cases, you might actually get a floating value like 0.9997 or 0.0001 instead of the actual integer frame numbers (not sure why exactly) so by rounding up the value, you can keep keys that are on the closest full frame for your target object. We also want to make sure not to have multiple entries of the same frame to speed things up later on.


##  ------------------------------------------------------------------------------------------------

##  Create a list of keyed frames from the source object

keepList = []
for param in ["posX", "posY", "posZ", "rotX", "rotY", "rotZ", "sclX", "sclY", "sclZ"]:
	parameter = source.kinematics.local.Parameters(param)
	if parameter.Keyable:
		FCurve = parameter.Source
		keys = FCurve.Keys
		for key in keys:
			if key.Time not in keepList:
				keepList.append(round(key.Time))

##  ------------------------------------------------------------------------------------------------

Now that we have a list of frames on which there are keys on our source object, we need to make a list of all the frames we want to delete keys from. We could build a list of all the keys from the target object, get the curves, keys and frames from that. Sometimes that can be a valid approach, but from my experience it’s usually faster to just use the timeline and work from there.

What we’ll do is create a list of frames on which we’d like to delete keys by going through the timeline and adding frames that can’t be found in our keepList to this new deleteList.


##  ------------------------------------------------------------------------------------------------

##  Create list of frames to delete
PCIn = xsi.GetValue("PlayControl.In")
PCOut = xsi.GetValue("PlayControl.Out")
deleteList = []
for frame in range(int(PCIn), int(PCOut+1)):
	if not frame in keepList:
		deleteList.append(frame)

##  ------------------------------------------------------------------------------------------------

Now that we have our list of frames to delete, it’s just a matter of deleting all keys for those frames. To be able to do that though, you’ll need a string containing the parameters to delete keys from.


##  ------------------------------------------------------------------------------------------------

##  Delete Keys from deleteList frames

for frame in deleteList:
	parameters = target.kinematics.local.Parameters.GetAsText()
	xsi.DeleteKeys(parameters, frame, frame, False, 0, "siAnimatedParameters")

##  ------------------------------------------------------------------------------------------------

Ok, we’re done! Of course this could probably be done some other ways, this is only a simple approach to start showing you the basics of writing small tools to make your lives easier. We could put in some error checking mechanisms to make sure the selection’s good, add the option to pick the objects instead of selecting them beforehand, we could rewrite it so that it can use more than 2 objects, a lot of improvements could be done to it but as far as simple solutions to solve a simple problem goes, this is good enough. This kind of tool might take anywhere from 5 minutes to a couple of hours to write depending on how comfortable you are with python, softimage, and how fast you can find stuff in the SDK help menu. The more you play around with the automation of tasks like these, the faster you’ll get!

If you have any questions or suggestions, feel free to comment. I’ll gladly take requests for tools and examples.

I’ll try to do a post every one or two weeks, depending on how much free time I get from work and life in general.

-Phil




Enter your email address to follow this blog and receive notifications of new posts by email.

Join 5 other subscribers