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

How do I change this script to run on a selected comp rather than having to run it *inside* it?

Contributor ,
Jun 21, 2022 Jun 21, 2022

I work in animation and a huge part of my day is comping SWF assets in AE. Under certain conditions, such as a camera move, the lines in SWF artwork will shimmer due to continuous rasterization of the SWF layers. There's a way around this by precomping the SWF assets and scaling them to 200%, then turning off continuous rasterization of the precomp (not the SWF layers) and scaling the precomp by 50% (thereby arriving back at 100% overall but without the shimmer).

 

I have a script which does the upscale part, which must be run inside of the SWF precomp. It changes the comp size to 3840x2160, and upscales all the SWFs 200%.

 

This works great, but it's only automates part of the operation. One level up, I have to manually set the precomp to 50% and turn off continuous rasterization. This gets tedious if a scene has dozens of characters, each with their own SWF precomp.

 

What I'd like to do is simply select the SWF precomp and run the script, and it perform the upscaling operation inside the precomp, then sets the scale of the precomp to 50% and turns off continuous rasterization. Ideally, I'd love this to be able to work on multiple selected precomps, looping through each of the (but this is wish list stuff – so bonus points if anyone can figure that out!).

 

I'll be honest, I'm still learning AE scripting. The script is cobbled together from a few places, albeit with a few modifications from me, so any help is greatly appreciated. Thank you!

 

 

myPanel.grp.group3.swf_fix.onClick = function() {

            app.beginUndoGroup("Scale to 4K")

            var activeComp = app.project.activeItem;

            // Scale the comp to 4K
            activeComp.width  = 3840;
            activeComp.height = 2160;

            // Add null
            var nullLayer = activeComp.layers.addNull();
            
            // Scale null to 1/4 size of comp
            nullLayer.position.setValue([activeComp.width/4,activeComp.height/4]);

            // Parent layers to null
            ParentUnparented(activeComp, nullLayer);
            
            // Scale null 200%
            nullLayer.transform.scale.setValue([200,200]);
            
            // Delete null
            nullLayer.remove();
            
            // Go through layers, parent if not already parented. This is temporary and required.
            function ParentUnparented(theComp, newParent)
               {
                  for (var i = 1; i <= theComp.numLayers; i++) {
                     var curLayer = theComp.layer(i);
                     var wasLocked = curLayer.locked;
                     curLayer.locked = false;
                     if (curLayer != newParent && curLayer.parent == null) {
                        curLayer.parent = newParent;
                     }
                     curLayer.locked = wasLocked
                  }
            }

         app.endUndoGroup();

         }

 

 

TOPICS
Scripting
925
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 , Jun 21, 2022 Jun 21, 2022

Sorry, I didn't read part 2 of your post. You could define variable s in your var declaration section, and then do this:

	// do stuff to the precomp layer

	s = precompLayer.transform.scale.value;
	precompLayer.transform.scale.setValue([s[0]/2,s[1]/2]);
	precompLayer.collapseTransformation = true;
Translate
Community Expert ,
Jun 21, 2022 Jun 21, 2022

I think I would change the workflow a little so that the script expects that you have precomp layers selected in the main comp. It could then do the down scaling and turning off the collapseTransformation atrribute on the precomp layers, and use layer.source to get to the corresponding precomps to do the part you already have coded.

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 ,
Jun 21, 2022 Jun 21, 2022

Thanks Dan, that definitely points me in the right direction as to the theory. It's been over a year since I dabbled in AE scripting so I'm a little rusty as to how to implement it into the code I already have. I'll need to think about it and research how to do it.

 

Would this also work for multiple selected precomps?

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 ,
Jun 21, 2022 Jun 21, 2022

Yes, sure. I'd structure like this (I'd also add a bunch of checks to make sure the activeItem is a comp and that each selected layer has a source and that the source is a CompItem--especially if other people would use the script):

 

var mainComp = app.project.activeItem;
var precompLayers = mainComp.selectedLayers;
var precompLayer;
var precomp;
for (var i = 0; i < precompLayers.length; i++){
	precompLayer = precompLayers[i];
	
	// do stuff to the precomp layer
	
	precomp = precompLayer.source;
		
	// do stuff inside the precomp
	
}

 

 

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 ,
Jun 21, 2022 Jun 21, 2022

Thank you Dan! I'm so close. 99% there. The stuff inside of the precomp is working great with your additions.

 

However, I know that my "do stuff to the precomp layer" code is incorrect…

 

(1) The code works, but it's affecting layer number 1, when I actually need it to affect selected layers. I know that this is due it referencing Layer(1), but I'm unsure how to change that to make it affect selected layers only. I tried "precompLayers.transform.scale.setValue([50,50]);" but I get an error that "undefined is not an object".

 

(2) I've realized that setting the scale to 50,50 is not actually what I need. What I need instead is to divide the current scale by 2. Eg, the original layer might be 180%, so I would want it to know be 90%. I'm unsure how to do that. I thought I might be on the right track with "mainComp.layer(1).setValue([mainComp.width/2,mainComp.height/2]);" but  I get an error "mainComp.layer(1).setValue is undefined"

 

 

app.beginUndoGroup("Upscale SWF")

var mainComp = app.project.activeItem;
var precompLayers = mainComp.selectedLayers;
var precompLayer;
var precomp;
for (var i = 0; i < precompLayers.length; i++){
	precompLayer = precompLayers[i];
	
	// do stuff to the precomp layer

      mainComp.layer(1).transform.scale.setValue([50,50]);
      mainComp.layer(1).collapseTransformation = true;
	
	precomp = precompLayer.source;

	// do stuff inside the precomp
	
      // Scale the comp to 4K
      precomp.width  = 3840;
      precomp.height = 2160;

      // Add null
      var nullLayer = precomp.layers.addNull();

      // Scale null to 1/4 size of comp
      nullLayer.position.setValue([precomp.width/4,precomp.height/4]);

      // Parent layers to null
      ParentUnparented(precomp, nullLayer);

      // Scale null 200%
      nullLayer.transform.scale.setValue([200,200]);

      // Delete null
      nullLayer.remove();

      //  Go through layers, parent if not already parented. This is temporary and required.
         function ParentUnparented(theComp, newParent)
            {
               for (var i = 1; i <= theComp.numLayers; i++) {
                  var curLayer = theComp.layer(i);
                  var wasLocked = curLayer.locked;
                  curLayer.locked = false;
                  if (curLayer != newParent && curLayer.parent == null) {
                     curLayer.parent = newParent;
                  }
                  curLayer.locked = wasLocked
               }
         }

}

app.endUndoGroup();

 

 

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 ,
Jun 21, 2022 Jun 21, 2022

I think it would be like this:

	// do stuff to the precomp layer

	precompLayer.transform.scale.setValue([50,50]);
	precompLayer.collapseTransformation = true;
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 ,
Jun 21, 2022 Jun 21, 2022

Sorry, I didn't read part 2 of your post. You could define variable s in your var declaration section, and then do this:

	// do stuff to the precomp layer

	s = precompLayer.transform.scale.value;
	precompLayer.transform.scale.setValue([s[0]/2,s[1]/2]);
	precompLayer.collapseTransformation = true;
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 ,
Jun 21, 2022 Jun 21, 2022
LATEST

Thanks Dan, that did it! I truly appreciate your patience on this.

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 ,
Jun 21, 2022 Jun 21, 2022

Again, thank you. Is there a way to set the scale to 50% of the current value, rather than entering 50 as the value? Eg, the original layer might be 180%, so I would want it to know be 90%. I'm unsure how to do that. In the GUI I would just go into the scale value and type "/2" after the number, so I'm looking for a way to do that with the script.

 

I feel like it's something close to precompLayer.layer.transform.scale * 0.5; but I get "invalid numeric result, divide by zero?"

 

I also realized a couple of errors in my code. I needed the collapse transform to be 'false' not 'true', and I needed the null to be a 3D layer in the precomp (due to the SWFs having 3D enabled). Here's where I'm currently at…

 

 

 

app.beginUndoGroup("Upscale SWF")

var mainComp = app.project.activeItem;
var precompLayers = mainComp.selectedLayers;
var precompLayer;
var precomp;
for (var i = 0; i < precompLayers.length; i++){
	precompLayer = precompLayers[i];
	
	// do stuff to the precomp layer

      precompLayer.transform.scale.setValue([50,50]);
      precompLayer.collapseTransformation = false;
	
	precomp = precompLayer.source;

	// do stuff inside the precomp
	
      // Scale the comp to 4K
      precomp.width  = 3840;
      precomp.height = 2160;

      // Add null
      var nullLayer = precomp.layers.addNull();

      // Make null 3D
      nullLayer.threeDLayer = true;

      // Center null to comp
      nullLayer.position.setValue([960,540,0]);

      // Parent layers to null
      ParentUnparented(precomp, nullLayer);

      // Scale null 200%
      nullLayer.transform.scale.setValue([200,200]);

      // Delete null
      nullLayer.remove();

      //  Go through layers, parent if not already parented. This is temporary and required.
         function ParentUnparented(theComp, newParent)
            {
               for (var i = 1; i <= theComp.numLayers; i++) {
                  var curLayer = theComp.layer(i);
                  var wasLocked = curLayer.locked;
                  curLayer.locked = false;
                  if (curLayer != newParent && curLayer.parent == null) {
                     curLayer.parent = newParent;
                  }
                  curLayer.locked = wasLocked
               }
         }

}

app.endUndoGroup();

 

 

 

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