Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

ExtendScript help for adding expression to shape layer properties

Participant ,
Nov 08, 2022 Nov 08, 2022

I'm brand new to ExtendScript, but know my way around expressions pretty well. I have a situation where I have mulitple AI vector layers in a comp that I want to convert to shape layers then add an expression to the stroke property of each. I've read some guides, posts, and the scripting reference, but am finding it hard getting any where.

 

The steps I would like to put in the script are:

  1.  Take the selected layer AI vector layer and create a shape layer from it (i.e. Create > Create paths from vector layer). I know I can use app.executeCommand(3973) for this.
  2.  Remove the " Outlines" text from the new layer name.
  3.  On the new shape layer, for all objects in all groups, add the following expression to the Stroke Width property:
       scaler = transform.scale[0];
       sWidth = thisComp.layer("control").effect("Stroke Width")("Slider").value;
       sWidth * (100/scaler);
     
    I'm hoping some smart scripters out there can get me started. 

 

Thanks!

TOPICS
How to , Scripting
1.7K
Translate
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 Expert , Feb 03, 2023 Feb 03, 2023

I haven't tested this, but I'd try wrapping the stroke access in a try/catch and just skip that property (with continue) if there's an error:

myGroup = myContents.property(i);
try{
	myStrokeWidth = myGroup.property("ADBE Vectors Group").property("ADBE Vector Graphic - Stroke").property("ADBE Vector Stroke Width");
	myStrokeWidth.expression = myExpr;
}catch (err){
	continue;
}
Translate
Community Expert ,
Nov 08, 2022 Nov 08, 2022

This may not be exactly right for your situation but it should get you headed in the right direction:

function test(){
	var myExpr = 'scaler = transform.scale[0];\r' +
		'sWidth = thisComp.layer("control").effect("Stroke Width")("Slider").value;\r' +
		'sWidth * (100/scaler);';
	var myComp = app.project.activeItem;
	var myLayers = myComp.selectedLayers;
	if (myLayers.length == 0){
		alert("No layer selected.");
		return;
	}
	var myLayer = myLayers[0];
	var oldName = myLayer.name;
	var oldIndex = myLayer.index;
	app.executeCommand(3973);
	var newLayer = myComp.layer(oldIndex);
	newLayer.name = oldName;
	var myContents = newLayer.property("ADBE Root Vectors Group");
	var myGroup;
	var myStrokeWidth;
	for (var i = 1; i <= myContents.numProperties; i++){
		myGroup = myContents.property(i);
		myStrokeWidth = myGroup.property("ADBE Vectors Group").property("ADBE Vector Graphic - Stroke").property("ADBE Vector Stroke Width");
		myStrokeWidth.expression = myExpr;
	}
}
test();
Translate
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
Participant ,
Nov 08, 2022 Nov 08, 2022

Thanks Dan. This works great and I was able to understand it well enough to make some minor modifications for my specific needs. I do have a couple of questions to clarify what's going on.

 

  1.  Is the following a correct correlation of the layer properties to the ExtendScript equivalent for a shape layer?
    • Contents = property("ADBE Root Vectors Group")
    • Group = property("ADBE Vectors Group")
    • Stroke = property("ADBE Vector Graphic - Stroke")
  2.  If I had multiple Strokes applied to a Group (Stroke 1, Stroke 2, Stroke 3, etc.), how would I target a specific one (say Stroke 2)? Would I use: 
    • property("ADBE Vector Graphic - Stroke"[2])
Translate
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 Expert ,
Nov 08, 2022 Nov 08, 2022

 

 

OK, so here's the same path to Stroke Width in both match name format:

layer("test.ai").property("ADBE Root Vectors Group").property("ADBE Vector Group").property("ADBE Vectors Group").property("ADBE Vector Graphic - Stroke").property("ADBE Vector Stroke Width")

and regular name format:

layer("test.ai").property("Contents").property("Group 1").property("Contents").property("Stroke 1").property("Stroke Width")

The problem with match names, is when you have multiples of the same element, they have the same name, so you might have to go to index numbers, so in this case, 

.property("ADBE Vector Graphic - Stroke")

would become:

.property(4)

or something like that. Or you could just use the regular names, which might be:

.property("Stroke 2")

 It's hard to be definitve because a lot depends on the structure of that particular shape layer--how many levels of contents, groups, etc.

Translate
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
Participant ,
Dec 09, 2022 Dec 09, 2022

Fabulous. Thanks for the detailed description, Dan.

Translate
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
Participant ,
Feb 03, 2023 Feb 03, 2023

I've been working with this script for a while and it's been running great. However, this week I've been receiving an error on some files: "Unable to execute script at line 29. Null is not an object."

 

After some investigation of the script and files, I see that some objects in the AI file are filled but do not have strokes. When the script converts this to the shape in AE, the AE shape layer group only contains a fill and no stroke. So the script gives an error and stops processing the rest of the groups.

 

I tried adding an if/then/else statemement to the for loop at the end as follows :

 

 

for (var i = 1; i <= myContents.numProperties; i++){
        if (myStrokeWidth == null) {i = i + 1} else { // If there is no stroke, move to next group;
        myGroup = myContents.property(i);
        myStrokeWidth = myGroup.property("ADBE Vectors Group").property("ADBE Vector Graphic - Stroke").property("ADBE Vector Stroke Width");
        myStrokeWidth.expression = myExpr;
        }
    }

 

However, this doesn't work and doesn't add the expression to any of the groups with strokes. What am I missing in this error checking?

 

Thanks

Translate
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 Expert ,
Feb 03, 2023 Feb 03, 2023

I haven't tested this, but I'd try wrapping the stroke access in a try/catch and just skip that property (with continue) if there's an error:

myGroup = myContents.property(i);
try{
	myStrokeWidth = myGroup.property("ADBE Vectors Group").property("ADBE Vector Graphic - Stroke").property("ADBE Vector Stroke Width");
	myStrokeWidth.expression = myExpr;
}catch (err){
	continue;
}
Translate
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
Participant ,
Feb 03, 2023 Feb 03, 2023
LATEST

That worked. Thanks Dan!

Translate
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