Copy link to clipboard
Copied
Hi guys,
I'm just getting started with extendScript, and I've run in to an issue.
I'm trying to set a keyframe to an (admittedly) large value, After Effects sets it to a value that is different than the value I pass in. It seems to be snapping more than rounding, and doing so inconsistently.
For example, these are the values I'm setting int he script, and what After Effects is setting on the keyframe
1248304.6823 1248304.625
-4720535.9958 -4720536
4092748.7335 4092748.75
You can see that it seems to be 'snapping' the values to increments of .025, but it does it inconsistently from one value to the next. Is there a setting I can set in the script to force it to use the actual value I want?
What's strange is that if I copy and paste those values into After Effects directly on the keyframes, it rounds them to 3 significant digits, as I would expect.
Is it just because my numbers are too large? And if so, why does After Effects have no trouble with the values?
Any ideas or insights would be much appreciated!
for (var i = 1; i <= app.project.numItems; i++) {
if (app.project.item(i) instanceof CompItem) {
var comp = app.project.item(i);
var textName = comp.layers.addText( 'test' );
textName.threeDLayer = true;
textName.position.setValueAtTime( 0, [ 1248304.6823, -4720535.9958, 4092748.7335 ] );
}
}
Zewt! You are a hero!
I took a modified approach to your idea:
I set the int and decimal parts of the value as positions on two null objects.
Then used an expression on the camera.position to combine those two values.
Finally, I used that script that I linked to convert the camera.position expressions to keyframes and deleted the nulls.
Doing it this way let me create just two separate null objects, and not have to create two for each axis (x,y,z).
Also, the slider control has a limit of 1,000,000 to
...Copy link to clipboard
Copied
I got the same result as you (AE CC 2014). This is a bit strange indeed. The rounding up to 0.025 px accuracy is not a crime, but the roundings appears to be quite random as you said.
I tried to investigate a bit more (see test below), it appears than it is not a 0.025 px rounding, it's something else, but i don't know how to interpret it.
Xavier
// the alert displays the value to be set, the value that has been set, and the diference (xPosition only, not full array)
var comp= app.project.activeItem;
var p = comp.layer(1).transform.position;
var x0, x, xx;
var res = "";
function random(a,b){return Math.round(a + (b-a)*Math.random());}; // a, a+1, ... b-1
for (var n=0, x0=1; n<10; n++, x0*=10) {
x = random(x0, x0*10)+Math.random();
res += x; // position[0] to be set
res += " ---> "
p.setValue([x, 0, 0]);
xx = p.value[0]; // position[0] that has been set
res += xx;
res += " (diff : ";
res += (xx-x);
res+= ")\r\r";
};
alert(res);
Copy link to clipboard
Copied
Yes, it really is quite strange.
Looking at your example, the difference seems to get larger as you enter bigger and bigger numbers.
And like you said, if it did that consistently for each value (i.e. it was actually rounding up/down to the nearest 0.025 px), it wouldn't be a problem. But as it is, I'm getting a lot of jitter in the keyframes because each one is different than the previous.
I don't suppose you have any ideas for how to work around this? Or to somehow trick AE into thinking the values were entered into the position value directly?
Thanks for your help.
Copy link to clipboard
Copied
It's just rounding to a 32-bit float. That's a bug, since the properties themselves seem to be 64-bit (on a quick look in the SDK) and it doesn't happen with expressions.
Copy link to clipboard
Copied
Thanks for clarifying the issue, Zewt.
I submitted a bug to Adobe, but it feels like I just sent it off into a black hole and am not hopeful about receiving a timely response.
As I mentioned, I'm new to the world of AE scripting. What I'm trying to do is export a camera move from an external product I'm developing. The script basically sets a camera keyframe in AE for each frame in my product. Is there any kind of workaround for this bug?
Maybe creating a script that somehow works with expressions so I can set the value correctly?
Again, thanks for you insight, and I appreciate your expertise in how all this works.
Copy link to clipboard
Copied
Yeah. I've had great response when reporting bugs on Photoshop, but with AFX it feels like shouting down a well.
The problem you're seeing (simplified) is that 32-bit floats can either store a really big number with a small amount of precision after the decimal point, or a really small number with lots of precision after the decimal point. You could try exporting the data as two separate numbers, and combining them with an expression.
For example, if you have the number 123456789.987654321, export it as two separate keys: one for the decimal part by calling Math.floor(n), 123456789, and one for the fractional part by subtracting it off, n-Math.floor(n): 0.987654321. Both of these numbers should store fine in two expression slider controls, eg. CameraWhole and CameraFrac. Then, combine them with an expression by simply adding them together. It'll give ugly data that'll be really hard to manipulate if you want to change it later and require an expression for a silly workaround that'll slow down AFX--but it should give the right results.
Copy link to clipboard
Copied
Ah, that's very interesting. I'll give that a shot, thanks!
I found this script to convert expressions into keyframes. which could help with the slowing down calculations via the expression by writing them to keyframes. But then again, that might introduce the same problem where the values get converted to a 32-bit float.
We'll see!
Copy link to clipboard
Copied
Zewt! You are a hero!
I took a modified approach to your idea:
I set the int and decimal parts of the value as positions on two null objects.
Then used an expression on the camera.position to combine those two values.
Finally, I used that script that I linked to convert the camera.position expressions to keyframes and deleted the nulls.
Doing it this way let me create just two separate null objects, and not have to create two for each axis (x,y,z).
Also, the slider control has a limit of 1,000,000 to -1,000,000 which wasn't enough for what I needed.
For any one in the future (or maybe me) who may stumble across this looking for a solution.
// Creating project
var project = app.newProject();
// Creating comp
var comp = project.items.addComp('untitled', 1920, 1080, 1, 15, 30);
// Open the comp
comp.openInViewer();
// Create a camera
var cameraLayer = comp.layers.addCamera( 'Camera', [
'${this.model.width / 2}',
'${this.model.height / 2}'
] );
var cameraPosition = cameraLayer.position;
var positionInts = comp.layers.addNull();
positionInts.name = 'positionInts';
positionInts.threeDLayer = true;
var positionDecimals = comp.layers.addNull();
positionDecimals.name = 'positionDecimals';
positionDecimals.threeDLayer = true;
// Set the int of all your values on the positionInts null
positionInts.position.setValuesAtTimes(
[0, 1, 2], [
[4518810, -71312864, -2158705],
[4522482, -71308958, -2158292],
[4533658, -71297341, -2157044]
]
);
// Set the decimal of all values on the positionDecimals null
positionDecimals.position.setValuesAtTimes(
[0, 1, 2], [
[0.6400621915236115, -0.80026875436306, -0.5924631282687187],
[0.0393883166834712, -0.00048755109310150146, -0.32361961202695966],
[0.004953828640282154, -0.6714665293693542, -0.026646549347788095]
]
);
// Create an expression on the camera position
cameraPosition.expression = '[ thisComp.layer("positionInts").transform.position[0] + thisComp.layer("positionDecimals").transform.position[0] , thisComp.layer("positionInts").transform.position[1] + thisComp.layer("positionDecimals").transform.position[1], thisComp.layer("positionInts").transform.position[2] + thisComp.layer("positionDecimals").transform.position[2] ];';
// Bake all the expression keyframes
function convertToKeyframes(theProperty) {
if (theProperty.canSetExpression && theProperty.expressionEnabled) {
theProperty.selected = true;
app.executeCommand(app.findMenuCommandId("Convert Expression to Keyframes"));
theProperty.selected = false;
}
}
convertToKeyframes( cameraPosition );
Thanks again for your input!
Copy link to clipboard
Copied
When you submit bugs through this form, we do read them. Specifically, one of the people who works just down the hall from me reads them and processes them. We can't respond to every one, though.
Copy link to clipboard
Copied
Thank you very much for your reply, Todd.
I did submit through that form and didn't mean to suggest that the issues aren't being read, but that it could be a while before a fix could actually turn up in AE, given what I'm sure is a large volume of submitted bugs and requests.
Find more inspiration, events, and resources on the new Adobe Community
Explore Now