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

Why does this work as a script but not as a script UI button?

Contributor ,
Nov 10, 2020 Nov 10, 2020

I have this script which I wrote to reduce a little tedium from my everyday workflow. It takes the selected SWF file in my project window, makes a comp from it, the comp then automatically becomes the active item, the comp is set to 1920x1080, the SWF is resized to fit, and it enables continuous rasterization. It works fine if I run it from the script menu.

 

// File > New Comp from Selection
app.executeCommand(2796);

// Change active comp size
var activeComp = app.project.activeItem;
activeComp.width  = 1920;
activeComp.height = 1080;

// Layer > Transform > Fit To Comp
app.executeCommand(2156);

// Set layer to Continous Rasterization
app.project.activeItem.selectedLayers[0].collapseTransformation = true;

 

However, I would like to run it from an existing ScriptUI toolbar. I've pasted the script in like so, but it doesn't work…

/////////////////// SWF Setup
myPanel.grp.group12.swfSetup.onClick = function() {

// File > New Comp from Selection
app.executeCommand(2796);

// Change active comp size
var activeComp = app.project.activeItem;
activeComp.width  = 1920;
activeComp.height = 1080;

// Layer > Transform > Fit To Comp
app.executeCommand(2156);

// Set layer to Continous Rasterization
app.project.activeItem.selectedLayers[0].collapseTransformation = true;
         
}

 It's worth noting that if I replace the above with something else from another portion of my ScriptUI script, the button works fine. So I know at least that the button is set up correctly. The problem is that it just does nothing when it's written as above.

 

Also, if I strip this Script UI down to just the first line, app.executeCommand(2796); it does nothing, so I think that is the problem.

TOPICS
Scripting
978
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

Enthusiast , Nov 10, 2020 Nov 10, 2020

var myName = myItem.name.substring(0, myItem.name.lastIndexOf("."));

var myComp = app.project.items.addComp(myName, etc

 

you could just stick myItem.name in your addComp but the above should strip off the extension

substring is a method for taking a range from a string (start char, end char). lastIndexOf returns the last position of the character you specify. This is general javascript so you can just google "javascript string methods" for that stuff, and you'll find a ton of other resources by doi

...
Translate
Enthusiast ,
Nov 10, 2020 Nov 10, 2020

Took me a while to package this into a script panel (better if you can post it that way for ease of testing) but yes I found the same thing. No new comp is created by the executeCommand. You can easily check this if you set up some debugging, like a $.writeln(app.project.activeItem.name) or even an alert(). You won't get far if you can't track down issues by testing variables and having debugger enabled to get error messages, as scripting is just one coding issue after another.

 

Relying on executeCommand when there are other options isn't a great idea. It's a hack. You can just use addComp instead then add the footage to it. Same for the Fit To Comp really. Divide comp dimension by footage dimension to get the correct scale.

 

Why doesn't it work? It could simply be that the focus has moved from the project panel to the script button so that menu command which requires project panel focus no longer works. executeCommand is often pretty fussy about things being set up exactly right.

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
Contributor ,
Nov 10, 2020 Nov 10, 2020

Yeah I figured as much, thanks for the explanation. 

 

So I have now started rebuilding my script, starting with…

 

app.project.items.addComp('Comp',1920,1080,1,60,24)
 
…which works, but my question now is how do I have it add the selected SWF into that comp? Is this possible, given that the focus is taken away once I click the button? Apologies, I'm fairly new to scripting, hence the use of "hacks" in my original script lol.
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
Enthusiast ,
Nov 10, 2020 Nov 10, 2020

I would use a variable to grab the item first before creating the comp (gotta be careful about doing things that might change the selection).

Something like:

var myItem = app.project.activeItem;

or taking it from app.project.selection[0];

or you can loop (for var x = 1; x < app.project.numItems; x++) through app.project.items looking for app.project.item(x).selected = true

and if so var myItem = app.project.item(x)

 

No shortage of options there. Then just:

var myComp = app.project.items.addComp...etc

var myLayer = myComp.layers.add(myItem);

 

That's all off top of my head so forgive any syntax errors!

There's a pretty big learning curve when first starting scripting. Nothing really makes sense. You don't know enough about enough things to do anything you want to do. Just keep plugging away and eventually it starts to click. If you're not already you should be using something like these as a resource:

https://ae-scripting.docsforadobe.dev

http://www.redefinery.com/ae/fundamentals/

 

 

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
Enthusiast ,
Nov 10, 2020 Nov 10, 2020

Oops my bad:

app.project.item(x).selected = true

will make that item selected, should be:

if (app.project.item(x).selected == true) myItem = app.project.item(x);

= is make equal, == is compare if equal (which returns either true or false)

Anyway you don't really need to loop through to grab your footage. But there's one typical coding error for you!

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
Contributor ,
Nov 10, 2020 Nov 10, 2020

Thanks! For now I've opted to keep it simple. I have a proof of concept version working…

var myItem = app.project.activeItem;
var myComp = app.project.items.addComp('Comp',1920,1080,1,60,24);
var myLayer = myComp.layers.add(myItem);
app.project.item(125).layer(1).transform.scale.setValue([200,200]);
app.project.item(125).layer(1).collapseTransformation = true;

However, I need to make it work for any new comp it creates, rather than for a single ITEM(125) comp. Ideally, the new comp would take the name of the SWF as its name, and then the script would look for a comp named that. I think. I quickly getting out of my depth here.

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
Contributor ,
Nov 10, 2020 Nov 10, 2020

A couple more minutes and I figured out what mistakes I made above.

So this is a more robust working version…

var myItem = app.project.activeItem;
var myComp = app.project.items.addComp('Comp',1920,1080,1,60,24);
myComp.layers.add(myItem);
myComp.layer(1).transform.scale.setValue([200,200]);
myComp.layer(1).collapseTransformation = true;

However, as mentioned above, I would still like the SWF name to be given to the comp name, and for the comp to be added to the current SWF folder rather than the root folder. However, those are minor things. Thanks for getting me this far! 

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
Enthusiast ,
Nov 10, 2020 Nov 10, 2020

var myName = myItem.name.substring(0, myItem.name.lastIndexOf("."));

var myComp = app.project.items.addComp(myName, etc

 

you could just stick myItem.name in your addComp but the above should strip off the extension

substring is a method for taking a range from a string (start char, end char). lastIndexOf returns the last position of the character you specify. This is general javascript so you can just google "javascript string methods" for that stuff, and you'll find a ton of other resources by doing so.

 

myComp.parentFolder = myItem.parentFolder;

 

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
Contributor ,
Nov 10, 2020 Nov 10, 2020

That's great, thank you so so much!

 

I didn't realize that's how you would capture the name. I'm starting to think a very nice addition might be possible. 

 

Do you know how I could extract only a section of the SWF file name and add that to the name of the comp? The SWF are named following a strict convention, and the characters I need are always 11 through 16. So if the name was "SH_207_ST-01-020_v05_NS.swf" I would only require "01-020" from the name.

 

I then want to take "01-020" and add it to the comp name like this "COMP_01-020_v01". Note the suffix version number at the end, which will always be "_v01".

 

And help would be greatly appreciated. No big deal if not, you've helped me plenty already! This would only be the icing on the cake.

 

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
Contributor ,
Nov 10, 2020 Nov 10, 2020

To prove I'm not completely useless, I did just figure out how to at least add the "COMP_" prefix and "_v01" suffix to the name haha.

 

var myItem = app.project.activeItem;
var myName = myItem.name.substring(0, myItem.name.lastIndexOf("."));
var myComp = app.project.items.addComp("COMP_"+myName+"_v01",1920,1080,1,60,24);
myComp.layers.add(myItem);
myComp.layer(1).transform.scale.setValue([200,200]);
myComp.layer(1).collapseTransformation = true;
myComp.duration = myComp.layer(1).source.duration;
myComp.parentFolder = myItem.parentFolder;
myComp.openInViewer();

 

I just need to figure out how to only extract a section of the string instead of the whole name.

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
Enthusiast ,
Nov 10, 2020 Nov 10, 2020

I'm kinda surprised you didn't figure it out.

myItem.name.substring(10, 16);

 

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
Contributor ,
Nov 10, 2020 Nov 10, 2020

wow. yeah. thanks again man. this will eventually add up to a big timesaver for me. Anything to sooth the daily grind is worth pursuing!

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
Contributor ,
Nov 16, 2020 Nov 16, 2020

Hey @Paul Tuersley , I wonder if you have a moment to help me refine my script further. I've adapted the script to work for multiple selections by adding a for loop. Now I can select all the SWFs in the scene and hit the button to add them all to a single comp.

 

However, in order to make this work I've had to disable the rename and parent folder lines at the top, otherwise I get errors. The rename error is "Undefined is not an object", and the parent folder error is "Unable to set parentFolder, undefined is not of the correct type". I assume that when I changed it to app.project.selection it broke those lines because it's no longer referencing a single selection?

 

The other problem is my 'for loop' for adding SWFs to the comp. My SWF names have a prefix number so that I can easily re-assemble the Flash scene in AE. For example 00_Dog.Swf, 01_Cat.swf, 02_Bird.swf, etc. But the current script places the layer order in reverse order starting with the highest number. It doesn't seem to matter what order I select them in the project window either. How can I reverse this so it runs the correct way around, lowest to highest?

 

Any help would be appreciated here. Thank you!

 

 

var items = app.project.selection;
            
// Extract characters 11 through 16
// var myName = items.name.substring(10, 16);

// Create comp
var myComp = app.project.items.addComp("COMP_"+myName+"_v01",1920,1080,1,60,24);

// Put comp in the same folder as the selected footage
// myComp.parentFolder = items.parentFolder;

for(var i = 0; i < items.length; i++) {

   var myItem = items[i];

   // Add selected footage, scale footage, and collapse tranformation
   myComp.layers.add(myItem);
   myComp.layer(1).transform.scale.setValue([200,200]);
   myComp.layer(1).collapseTransformation = true;
}

   // Trim comp to duration of footage
   myComp.duration = myComp.layer(1).source.duration;

   // Deselects all items in the Project window
   var selectedItems = app.project.selection;
   for (var i = 0; i < selectedItems.length; i++)
      selectedItems[i].selected = false;

   // Selects the new comp
   myComp.selected = true;

   // Open comp
   myComp.openInViewer();

 

 

For reference, this is the previous script which works fine for single selections…

 

var myItem = app.project.activeItem;
            
// Extract characters 11 through 16
var myName = myItem.name.substring(10, 16);
            
// var myName = myItem.name.substring(0, myItem.name.lastIndexOf(".")); // Copies the name, minus the extension
var myComp = app.project.items.addComp("COMP_"+myName+"_v01",1920,1080,1,60,24);
            
// Add selected footage, scale footage, and collapse tranformation
myComp.layers.add(myItem);
myComp.layer(1).transform.scale.setValue([200,200]);
myComp.layer(1).collapseTransformation = true;
            
// Trim comp to duration of footage
myComp.duration = myComp.layer(1).source.duration;
            
// Ensure comp is created in the same folder as the selected footage
myComp.parentFolder = myItem.parentFolder;
            
// Deselects all items in the Project window
var selectedItems = app.project.selection;
for (var i = 0; i < selectedItems.length; i++)   // Note: selection array starts at 0
selectedItems[i].selected = false;
            
// Selects the new comp
myComp.selected = true;
            
// Open comp
myComp.openInViewer();

 

 

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
Enthusiast ,
Nov 16, 2020 Nov 16, 2020

myComp.parentFolder = items.parentFolder;

This isn't working because you can't say 'put it in the same folder as all the items' folder'. You can say to put it in one of the item's folder. I assume as you did this they're all in thesame folder?

myComp.parentFolder = items[0].parentFolder;

 

Same thing for the name. You want the name to be the name of all the selected items? It doesn't make sense. I'm not even sure what you want the comp named after when you're putting multiple items into it. Kinda strange that you realised app.project.selection / myItem was an array of items and figured out how to access the individual items inside it and yet couldn't make this extra leap.

 

I haven't tested it but from your description app.project.selection is always in the alphabetical sort order of items in the project panel. So one simple way would be to just add the items in reverse order by doing a reverse for loop:

for (var i = items.length-1; i >= 0; i--) {

 

Alternatively, after you're done tweaking the layer, move it to the bottom of the stack. So at the end of but still inside the for loop:

if (myComp.numLayers > 1) myComp.layer(1).moveToEnd();

 

 

 

 

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
Contributor ,
Nov 16, 2020 Nov 16, 2020

That reverse for loop worked, thank you.

 

Re: the renaming, the first part of the footage name is always the same, per episode. Example: 

EP_207_ST-09-002_v05 Man.swf

EP_207_ST-09-002_v05 Woman.swf

EP_207_ST-09-002_v05 Dog.swf

I was just hoping that it could access any one of those names to get the section that is always the same.

 

Re: the parent folder, yes the SWFs are all in the same folder.

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
Contributor ,
Nov 16, 2020 Nov 16, 2020
LATEST

Ok this works…

var items = app.project.selection;
            
// Extract characters 11 through 16
var myName = items[0].name.substring(10, 16);

// Create comp
var myComp = app.project.items.addComp("COMP_"+myName+"_v01",1920,1080,1,60,24);

// Put comp in the same folder as the selected footage
myComp.parentFolder = items[0].parentFolder;

// Reverse for loop, so that the numerical layer names are listed correctly 00-99
for (var i = items.length-1; i >= 0; i--) {

   var myItem = items[i];

   // Remove the first 23 characters from the layer name
   var remove23 = myItem.name.substring(23);

   // Add selected footage, scale footage, and collapse tranformation
   myComp.layers.add(myItem);
   myComp.layer(1).transform.scale.setValue([200,200]);
   myComp.layer(1).collapseTransformation = true;
   myComp.layer(1).name = remove23;
}

 // Trim comp to duration of footage
 myComp.duration = myComp.layer(1).source.duration;

// Deselects all items in the Project window
var selectedItems = app.project.selection;
for (var i = 0; i < selectedItems.length; i++)
   selectedItems[i].selected = false;

// Selects the new comp
myComp.selected = true;

// Open comp
myComp.openInViewer();

 

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