Activity › Forums › Adobe After Effects Expressions › Script mask shape to motion path
-
Script mask shape to motion path
Posted by Benoit Kergosien on March 19, 2015 at 7:08 amHi guys,
I’m trying to copy via scripting the mask shape to the position property of my layer.
This post is based on this older one from 2013 : script mask shape to motion path
Since my last post there I tried to apply the code of Xavier but I can’t achieve to arrange the interval of time into an array.
=========================================================
var myComp=app.project.activeItem;
var myLayer=myComp.selectedLayers[0];
var myMask=myLayer.mask(1);
var myTarget=myLayer.transform.position;
var times=[0,2];var shape=myMask.maskPath.value,
verts=shape.vertices,
inTan=shape.inTangents,
outTan=shape.outTangents,
numVerts=verts.length;if (shape.closed) {verts.push(verts[0]); inTan.push(inTan[0]); outTan.push(outTan[0]); numVerts++;};
for (var k=0; k < numVerts; k++) inTan [k][2] = outTan[k][2] = 0;
myTarget.setValuesAtTimes(times,verts);
for (var idx, k=0; k < numVerts; k++)
{
idx=myTarget.nearestKeyIndex(times[k]);
target.setSpatialTangentsAtKey(idx, inTan[k], outTan[k]);
}=========================================================
What do I do wrong? How to declare this interval of time?
Thanks
Benoit.
Benoit Kergosien replied 11 years, 1 month ago 2 Members · 12 Replies -
12 Replies
-
Xavier Gomez
March 19, 2015 at 7:57 amtimes is not an array of the form [minTime, maxTime] but an array of the form [keyTime(0), keyTime[1],…, keyTime[numVerts-1]]: as many keyframes in the position property as vertices in the shape.
For instance:
var step = 2/(numVerts-1);
for (k=0; k<numVerts; k++) times[k] = k*step; -
Benoit Kergosien
March 19, 2015 at 1:09 pmHi Xavier,
thanks for your quick answer, it worked like a charm.
Now I try to copy the motion path to a point control instead of the position property and I have got this error :
“After Effects error: Unable to call “setSpatialTangentsAtKey” because of parameter 2. Value array does not have 2 elements.”
=============================
var myComp=app.project.activeItem;
var myLayer=myComp.selectedLayers[0];
var myMask=myLayer.mask(1);
var myTarget=myLayer.property(“Effects”).property(“Point Control”).property(“Point”);
var times=new Array();var shape=myMask.maskPath.value,
verts=shape.vertices,
inTan=shape.inTangents,
outTan=shape.outTangents,
numVerts=verts.length;var step = 2/(numVerts-1);
for (k=0; k -
Xavier Gomez
March 19, 2015 at 1:45 pmWell, the original post was to copy of shape to a motion path in a position property, and position properties are 3D (even for a 2D layer). If you are copying to a true 2D property like a point control, then skip the part that imbeds 2D to 3D, ie that line:
for (var k=0; k < numVerts; k++) inTan [k][2] = outTan[k][2] = 0;(remove it).
-
Benoit Kergosien
March 19, 2015 at 2:50 pmOh… Apologies Xavier.
I really have to comment the code since the begining of my tests.
BTW is there a way to test if the var myTarget is 2D or 3D? To skip the injection of 2D tangents into 3D if my Target is a true 2D property with an if/else statement.
Thanks.
Benoit
-
Xavier Gomez
March 19, 2015 at 2:59 pmUse the propertyValueType attribute (see AE scripting guide at the “Property” section):
p is a 2D property <====> p.propertyValueType === PropertyValueType[p.isSpatial ? “TwoD_SPATIAL” : “TwoD”];
p is a 3D property <====> p.propertyValueType === PropertyValueType[p.isSpatial ? “ThreeD_SPATIAL” : “ThreeD”];
Note that the dimension is not the same for expression and for scripting.
In expression context, the position property is 2D for 2D layers, but for script it is always 3D.Scripting tolerates setting a 2D value in a 3D spatial prop, but there is no tolerance for spatial tangents and for temporal ease, so before setting spatial tangents and/or keyframease you really have to check the dimension.
Xavier.
-
Xavier Gomez
March 19, 2015 at 3:02 pmEdit : if you already know that the property is 2D or 3D, you can also use p.value.length (the length of the value array). It’s clearer/faster.
-
Benoit Kergosien
March 20, 2015 at 9:21 amHi Xavier,
First of all, big thanks for your time.
I didn’t have time to test your last piece of code ’cause I’m stucked with the creation of Expression Controls on my layer.When I create only one of those (Target) the code works properly but when I add another one (mySlider) the code breaks.
=======================
var myComp=app.project.activeItem;
var myLayer=myComp.selectedLayers[0];
var myMask=myLayer.mask(1);
var Target=myLayer.property(“Effects”).addProperty(“Point Control”);
Target.name=”myTarget”;
var myTarget=myLayer.property(“Effects”).property(“myTarget”).property(“Point”);var mySlider=myLayer.property(“Effects”).addProperty(“Slider Control”);
mySlider.name=”mySlider”;var times=new Array();
var shape=myMask.maskPath.value,
verts=shape.vertices,
inTan=shape.inTangents,
outTan=shape.outTangents,
numVerts=verts.length;var step = 2/(numVerts-1);
for (k=0; k -
Xavier Gomez
March 20, 2015 at 10:10 amWhen you add a new effect to a layer, previous references to anything inside the layer effects get invalidated.
If you need to add several effects and keep a reference to all of them during the execution of the script, you should wait to have set them all to declare variables.var myComp=app.project.activeItem;
var myLayer=myComp.selectedLayers[0];
var myMask=myLayer.mask(1);var N=myLayer.numProperties;
myLayer.property(“Effects”).addProperty(“Point Control”);
myLayer.property(“Effects”).addProperty(“Slider Control”);var Target=myLayer.property(“Effects”).property(N+1);
Target.name=”myTarget”;
var myTarget=Target.property(“Point”);var mySlider=myLayer.property(“Effects”).property(N+2);
mySlider.name=”mySlider”;N+=2;// the actual number of effects now
Xavier
-
Benoit Kergosien
March 20, 2015 at 10:32 amThanks for those explanations Xavier, you are very helpful!
Benoit
-
Benoit Kergosien
March 21, 2015 at 1:50 pmI tried to accomplish that you explain to me yesterday but I’ve got error on the line:
var Target=myLayer.property(“Effects”).property(mynumEffects+1);
“After Effect error; Unable to call “property” because of parameter 1. Value 12 out of range 1 to 3.”
==========
var myComp=app.project.activeItem;
var myLayer=myComp.selectedLayers[0];
var myMask=myLayer.mask(1);
var times=new Array();// Creation of Effects
var mynumEffects=myLayer.numProperties;
myLayer.property(“Effects”).addProperty(“Point Control”);
myLayer.property(“Effects”).addProperty(“Slider Control”);
myLayer.property(“Effects”).addProperty(“Slider Control”);// Customisation of Effects
var Target=myLayer.property(“Effects”).property(mynumEffects+1);
Target.name=”myTarget”;
var myTarget=Target.property(“Point”);var slider01=myLayer.property(“Effects”).property(mynumEffects+2);
slider01.name=”mySlider01″;
var mySlider01=slider01.property(“Slider”);var slider02=myLayer.property(“Effects”).property(mynumEffects+3);
slider02.name=”mySlider02″;
var mySlider02=slider02.property(“Slider”);mynumEffects+=3;
// Read path content
var shape=myMask.maskPath.value,
verts=shape.vertices,
inTan=shape.inTangents,
outTan=shape.outTangents,
numVerts=verts.length;// In case of closed shape
if (shape.closed) {verts.push(verts[0]); inTan.push(inTan[0]); outTan.push(outTan[0]); numVerts++;};// Inject 2D tangents into 3D property (tangents for a motion path always 3D, even for 2D)
//for (var k=0; k < numVerts; k++) inTan [k][2] = outTan[k][2] = 0;// Interval of time within wich the animation is adapted
var step = 2/(numVerts-1);
for (k=0; k
Reply to this Discussion! Login or Sign Up