set rotoBezier property via scripting

Community Beginner ,
Aug 04, 2022 Aug 04, 2022

Copy link to clipboard

Copied

I'm creating AE paths from data, setting the paths to rotobezier mode gives nice curvey shapes that fit through the data points.

 

Running into issues though when I try and set this via jsx. If I manually change the rotobezier mode for a mask, I can query the rotoBezier property:

myLayer = mainComp.layers.byName('my cool layer');
mask = myLayer.property('Masks').property('Mask 1');
alert(mask.rotoBezier);

but if I try and set it:

mask.rotoBezier=true;

I can query it and see that its true, even the menu option under Layer -> Mask and Shape path -> Rotobezier has the tick next to it to show its active, but the comp itself doesn't change mode.

 

Further, if I try the same thing but with a path instead of mask, I can't get it to return any value, and I definitely can't get it to update in the comp.

 

Any ideas?

TOPICS
Scripting

Views

74

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Beginner , Aug 08, 2022 Aug 08, 2022

Hmm, I was trying to keep the comp template I'm building as tidy as possible, I'm sure linking masks and paths via expressions would've worked, but hoped to only use that method as a last resort!

 

Someone on Discord pointed out I could call the menu function directly with

 

app.executeCommand(app.findMenuCommandId("RotoBezier"))

 

This requires the current selection to be exact, only the layer and path can be selected; anything else selected will make the command silently fail. I ended up doing somet

...

Likes

Translate

Translate
Adobe Community Professional ,
Aug 05, 2022 Aug 05, 2022

Copy link to clipboard

Copied

This seemed to work to convert a mask path from bezier to rotoBezier (I didn't try it with shapes):

var layer = app.project.activeItem.layer(1);
var masksGroup = layer.property("ADBE Mask Parade");
var mask = masksGroup.property(1);
var maskPath = mask.property("ADBE Mask Shape");
var myShape = maskPath.value;
myShape.inTangents = [];
myShape.outTangents = [];
mask.rotoBezier = true;
maskPath.setValue(myShape);

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Aug 05, 2022 Aug 05, 2022

Copy link to clipboard

Copied

Thanks for the response! 

 

I tried that on my setup with a pre-existing mask, and it was strangely non deterministic; would work once, then stop working, or not work at all.

 

I made a little 2 minute explainer for what I'm seeing if that's easier to follow:

 

https://www.youtube.com/watch?v=qgLeRKyX0YU&ab_channel=mattestela

 

Found a couple of things that made it a little more reliable for masks, but unfortunately doesn't work for paths.

 

Using empty arrays for the inTangents and outTangents doesn't work if the original shape is all corner points. If I use the vertices array to construct 'proper' in and out tangents based on another forum post, that seems to make it happy... except that it needs one more thing. I found I have to essentially reset the rotoBezier toggle to false first, then true. It's clearer in the video, but I get odd results where sometimes it just doesn't work, or the mask effect is updated, but the handle and paths aren't.

 

Here's my updates to Dan's code:

var layer = app.project.activeItem.layer(1);
var masksGroup = layer.property("ADBE Mask Parade");
var mask = masksGroup.property(1);
var maskPath = mask.property("ADBE Mask Shape");
var myShape = maskPath.value;
vertices = maskPath.value.vertices;
// create proper in/out tangents
for(i = 0; i <vertices.length; i++) {
    inTangents[i] = [1,0];
    outTangents[i] = [-1,0];
}
myShape.inTangents = inTangents;
myShape.outTangents = outTangents;
// set rotobezier toggle false, then true
mask.rotoBezier = false;
mask.rotoBezier = true;
maskPath.setValue(myShape);

 

...and while this is all interesting, none of this works with paths, which is what I really need! 

 

Anyone got ideas?

Here's what I think should be working for a path, but I see no visual change, and in fact when I r.click on the path in the layers panel, I can see the RotoBezier toggle isn't enabled, which implies I'm missing something:

pathlayer = app.project.activeItem.layer(1);
path = pathLayer.content("ADBE Vector Shape - Group");
shape = path.property("ADBE Vector Shape");

myShape = shape.value;
vertices = shape.value.vertices;
for(i = 0; i <vertices.length; i++) {
    inTangents[i] = [1,0];
    outTangents[i] = [-1,0];
}
myShape.vertices = vertices;
myShape.inTangents = inTangents;
myShape.outTangents = outTangents;

shape.setValue(myShape);
path.rotoBezier = false;
path.rotoBezier = true;

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Aug 06, 2022 Aug 06, 2022

Copy link to clipboard

Copied

Create the path as a mask, link the shape path to the mask with a simple pickwhip expression.

 

Mylenium

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Aug 08, 2022 Aug 08, 2022

Copy link to clipboard

Copied

Hmm, I was trying to keep the comp template I'm building as tidy as possible, I'm sure linking masks and paths via expressions would've worked, but hoped to only use that method as a last resort!

 

Someone on Discord pointed out I could call the menu function directly with

 

app.executeCommand(app.findMenuCommandId("RotoBezier"))

 

This requires the current selection to be exact, only the layer and path can be selected; anything else selected will make the command silently fail. I ended up doing something like this:

 

 

// deselect all for rotobezier weirdness later
sel = mainComp.selectedLayers;
for (i=0; i<sel.length;i++) {
    sel[i].selected = false;
}

// stuff happens, make layers, make paths, then..

layer.selected = true;
pathGroup = layer.content.property("Path 1");
pathGroup.selected = true;
app.executeCommand(app.findMenuCommandId("RotoBezier"))
// deselect for next go round
layer.selected = false;
pathGroup.selected = false;

 

It's a kludge, but only has to run once when I create this template, so it'll do.

 

Thanks for the help all!

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Aug 08, 2022 Aug 08, 2022

Copy link to clipboard

Copied

LATEST

Oh as an aside, I tested to see if doing the same selection trick would mean setting pathGroup.rotoBezier=true would work, but it didn't.

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines