Solid scale to size

Find out why the . goes before the /

Moderator: Paul Tuersley

Post Reply
Mike A
Posts: 5
Joined: July 2nd, 2009, 4:17 am

Hello scripters -
let me give you fair warning: I'm an absolute scripting newby -  so please speak in code of one syllable ; )

I've created a simple script to do a scale modification on solids. I've used the 'replaceWithSolid' function to do so. The basic functionality of the script is working fine for solids 'used once', but I don't know how to deal with solid layers that have a common solid source.


My basic script is below:
=========================

//Solid scale to size
//Script to replace selected solids, which may have a non-100% scale factor, with a visibily matching solid at 100% scale.
// Mike Abbott // http://www.mikeabbott.info
// Version 0003
// 09 June 2017.


main();
function main(){

    
//Create undo group
app.beginUndoGroup("Scale to Size script");

//variables
var numLayers;
var curLayer;
var sColor;
var sName;
var sWidth;
var sHeight;
var sPAR;

// find the number of selected layers
numLayers = app.project.activeItem.selectedLayers.length;
if (numLayers <1){
    alert ("Please select some solid layers");
    return;
}

// iterate through the selected layers
for (var i=0; i < numLayers;  i++){
    
    //set curLayer to the first selected layer
    curLayer = app.project.activeItem.selectedLayers
    
    //test if selected layer is a solid based layer
     if (curLayer.source != null && curLayer.adjustmentLayer == false && curLayer.source.mainSource instanceof SolidSource){
       
        //store parameters of the selected solid layer
        sColor = curLayer.source.mainSource.color;
        sName = curLayer.name;
        sWidth = curLayer.width;
        sHeight = curLayer.height;
        sPAR = curLayer.source.pixelAspect;
        sScale = [Math.abs(curLayer.scale.value[0]), Math.abs(curLayer.scale.value[1])];
        
        //replace the solid source with a matching solid with width and height calculated from it's scale
        curLayer.source.replaceWithSolid(sColor, sName, Math.round(sWidth/(100/sScale[0])), Math.round(sHeight/(100/sScale[1])), sPAR);
        
        //set layer scale to 100%
        curLayer.scale.setValue([100,100,100]);
    }
}

alert ("Solid scale to size done!");

app.endUndoGroup();
}

=======================

I'd appreciate help in two areas:

1. A critique of the above - it's my first script. What should I have done differently?

2. This script fails miserably when multiple layers have a common solid source - changing the size of the source solid to fit 'layer 1' obviously affects other layers using that source. Any suggestions on how I can test for and work around this?
wysee
Posts: 7
Joined: November 21st, 2016, 9:24 am

Hi Mike,

You'll have to create new solid for each layer selected. Solid can only be created from a comp layer collection. Because you don't want to screw up your actual comp and loop by creating new layers in it and therefore changing the indexes and layer numbers, you can create a new comp, add a new solid for every layer selected in the original comp, replace them with the new solid, and then remove the temp comp.
You could also create an array to store the original solids, and remove them at the end. If you do so, some layers using the same source, be careful not to push the same source twice in the array... here's your code with my suggestion. there might be a better way but this one seems to work fine : 

//Solid scale to size
//Script to replace selected solids, which may have a non-100% scale factor, with a visibily matching solid at 100% scale.
// Mike Abbott // http://www.mikeabbott.info
// Version 0003
// 09 June 2017.


main();
function main(){

    
//Create undo group
app.beginUndoGroup("Scale to Size script");

//variables
var numLayers;
var curLayer;
var sColor;
var sName;
var sWidth;
var sHeight;
var sPAR;
// Add a temp comp to create the new solids;
var tempComp = app.project.activeItem.duplicate();
// find the number of selected layers
numLayers = app.project.activeItem.selectedLayers.length;
if (numLayers <1){
    alert ("Please select some solid layers");
    return;
}


// iterate through the selected layers
for (var i=0; i < numLayers;  i++){
    
    //set curLayer to the first selected layer
    curLayer = app.project.activeItem.selectedLayers
    
    //test if selected layer is a solid based layer
     if (curLayer.source != null && curLayer.adjustmentLayer == false && curLayer.source.mainSource instanceof SolidSource){
       
       
       
        //store parameters of the selected solid layer
        sColor = curLayer.source.mainSource.color;
        sName = curLayer.name;
        sWidth = curLayer.width;
        sHeight = curLayer.height;
        sPAR = curLayer.source.pixelAspect;
        sScale = [Math.abs(curLayer.scale.value[0]), Math.abs(curLayer.scale.value[1])];
        
        // create a new solid based on selected solid parameters.
        var newSolid = tempComp.layers.addSolid(sColor, sName, sWidth, sHeight, sPAR, app.project.activeItem.duration);
        var newSolidSource= newSolid.source;
        curLayer.replaceSource(newSolidSource,true);
        
        //replace the solid source with a matching solid with width and height calculated from it's scale
        curLayer.source.replaceWithSolid(sColor, sName, Math.round(sWidth/(100/sScale[0])), Math.round(sHeight/(100/sScale[1])), sPAR);
        
        //set layer scale to 100%
        curLayer.scale.setValue([100,100,100]);
    }
}
// remove temp comp from the project
tempComp.remove();


alert ("Solid scale to size done!");

app.endUndoGroup();
}


Ben
Mike A
Posts: 5
Joined: July 2nd, 2009, 4:17 am

Ben - that's an awesome reply - many thanks!

I'll take this away and study it and see if I can follow how you've worked the magic : )
I'm just struggling to get my head fully around the details of the syntax and scripting guide at the moment, but I'm sure that working through what you've put together will be a great help.
I really appreciate the response and contribution.

Mike
Post Reply