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

Is it possible to automate or create a script to duplicate links and activate/deactivate Layer Comp?

Community Beginner ,
May 30, 2024 May 30, 2024

For example, if I have 50 .psd images in my file, which I need to duplicate each one, so two links for each image.

The top image needs to have only a certain group/layer activated using the Layer Comps tool, then the second link under that needs to have everything deactivated but leaving only a layer which needs to be in multiply mode.

Basically two links, one for the model, another for the model's shadow.

What's the best approach to do that?

TOPICS
How to
2.4K
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
New Here ,
May 31, 2024 May 31, 2024

I had the same problem with shadows that you have that was resolved by using paths instead of layer comps.

I have a script that searches all images in a doc containing two layers with fixed names. When such an image is found it :

- duplicates the image,

- applies the 'packshot' path to the foremost image

- applies the 'full image' path with multiply mode to the bottom one

- groups the two images together to move them more easily when needed.

Maybe this could be adapted to your use of Layer Comps (but I never used those so not sure of how to address them).

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 Beginner ,
May 31, 2024 May 31, 2024

Thanks, but in my case I have the model hair and "delicated" stuff like that, it's a bit impossible to make that work with a path, so a mask is the way to go...

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 Beginner ,
Jun 01, 2024 Jun 01, 2024

After tweaking, playing around, trying to get help on Chatgpt but no success, I ended up with this script:

It's doing some parts correctly:

- It duplicates the link and sets to multiply, it enters the "object layer options" and hides the folder modelo but the layer "fundo branco" that i also need to hide, it doesn't...

- in the original link i need to hide the group "fundo" but its not doing

- after it runs, it gives me this error: Error occurred: ReferenceError: Object is invalid

 

script:

 

var lnk = app.activeDocument.links.everyItem().getElements();
var fileNames = [];

// Generate a list of file names for all selected images
for (var i = 0; i < lnk.length; i++) {
if (lnk[i].parent.constructor.name == "Image") {
fileNames.push(lnk[i].name);
}
}

// Iterate through the list of file names
for (var j = 0; j < fileNames.length; j++) {
var fileName = fileNames[j];

// Find the original image by file name
for (var k = 0; k < lnk.length; k++) {
if (lnk[k].name === fileName && lnk[k].parent.constructor.name == "Image") {
var originalImage = lnk[k].parent.parent;

// Duplicate the original image
var dup = originalImage.duplicate();

// Set the top link (original image) to Multiply
originalImage.transparencySettings.blendingSettings.blendMode = BlendMode.MULTIPLY;

// Set the duplicated image to Normal
dup.transparencySettings.blendingSettings.blendMode = BlendMode.NORMAL;

try {
// Adjust visibility of layers in the original image
var graphicLayerOptionsOriginal = originalImage.images[0].graphicLayerOptions;
var modeloGroupOriginal = graphicLayerOptionsOriginal.graphicLayers.itemByName("Edicao").graphicLayers.itemByName("Modelo");
if (modeloGroupOriginal.isValid) {
modeloGroupOriginal.currentVisibility = false;
}

var fundoBrancoLayerOriginal = graphicLayerOptionsOriginal.graphicLayers.itemByName("Edicao").graphicLayers.itemByName("Fundo Branco");
if (fundoBrancoLayerOriginal.isValid) {
fundoBrancoLayerOriginal.currentVisibility = false;
}

// Deactivate visibility for "Fundo" folder in the duplicated image
var graphicLayerOptionsDup = dup.images[0].graphicLayerOptions;
var fundoFolderDup = graphicLayerOptionsDup.graphicLayers.itemByName("Fundo");
if (fundoFolderDup.isValid) {
fundoFolderDup.currentVisibility = false;
}

// Iterate through all layers in the duplicated image and deactivate their visibility
var layers = graphicLayerOptionsDup.graphicLayers.everyItem().getElements();
for (var l = 0; l < layers.length; l++) {
layers[l].currentVisibility = false;
}
} catch (error) {
alert("Error occurred: " + error);
}

break;
}
}
}

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
LEGEND ,
Jun 01, 2024 Jun 01, 2024

@ril3ydx 

 

I think problem is in the fact that your "Fundo Branco" layer is in the "Fundo" group - and not in the root...

 

 

originalImage.images[0].graphicLayerOptions.graphicLayers.itemByName("Edicao").graphicLayers.itemByName("Fundo").graphicLayers.itemByName("Fundo Branco");

 

 

This should work:

 

 

originalImage.images[0].graphicLayerOptions.graphicLayers.itemByName("Edicao").graphicLayers.itemByName("Fundo").graphicLayers.itemByName("Sombra").currentVisibility = false;
originalImage.images[0].graphicLayerOptions.graphicLayers.itemByName("Edicao").graphicLayers.itemByName("Fundo").graphicLayers.itemByName("Fundo Branco").currentVisibility = false;

 

 

Or this in short:

 

originalImage.images[0].graphicLayerOptions.graphicLayers.itemByName("Edicao").graphicLayers.itemByName("Fundo").currentVisibility = false;

 

 

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 02, 2024 Jun 02, 2024

My first version did not consider groups. This loops through the groups recursively and gets a layer by name-- the 2nd parameter in the getGraphicLayer() function

 

var lnk = app.activeDocument.links.everyItem().getElements()

var obj, dup, sh, glc;
for (var i = 0; i < lnk.length; i++){
    if (lnk[i].parent.constructor.name == "Image") {
        obj = lnk[i].parent.parent
        dup = obj.duplicate().images[0];
        glc = dup.graphicLayerOptions.graphicLayers;

        getGraphicLayer(glc, "Modelo").currentVisibility = true;
        getGraphicLayer(glc, "Sombra").currentVisibility = false;
        
        obj.transparencySettings.blendingSettings.blendMode = BlendMode.MULTIPLY
    } 
};   

/**
* Recursively get an image’s graphic layer by name 
* @ param the root graphic layer group 
* @ param the name of the graphic layer to get 
* @ return the graphiclayer 
*/
function getGraphicLayer(gl, n) {
    for (var i = 0; i < gl.length; i++){
        if (gl[i].name == n) {
            return gl[i]
        } else if (gl[i].hasOwnProperty("graphicLayers") && gl[i].graphicLayers.length) {
            var r = getGraphicLayer(gl[i].graphicLayers, n)
            if(r) return r
        } 
    };  
}
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 03, 2024 Jun 03, 2024

Also, another way to do this would be with a function that returns all of the graphic layers as an array, which might be useful with deeply nested groups where the layers might have the same names. Here I have a single image direct selected, and the alert lists all of its graphic layers:

 

var gl = app.activeDocument.selection[0].graphicLayerOptions.graphicLayers;
var ga = getAllGraphicLayers(gl);
var s ="Image Graphic Layers \r"
for (var i = 0; i < ga.length; i++){
    s+= ga[i].name + "\r"
};   

alert(s)


/**
* Gets all of an image’s graphic layers as an array
* @ param the root graphic layer group 
* @ return an array of graphic layers 
*/
function getAllGraphicLayers(gl) {
    var gla = []
    for (var i = 0; i < gl.length; i++){
        if (gl[i].graphicLayers.length == 0) {
            gla.push(gl[i])
        } else if (gl[i].hasOwnProperty("graphicLayers")) {
            gla.push(gl[i])
            gla = gla.concat(getAllGraphicLayers(gl[i].graphicLayers));
        } 
    }; 
    if(gla.length){
        return gla
    }  
}

 

 

Screen Shot 1.png

 

 

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
LEGEND ,
Jun 03, 2024 Jun 03, 2024

@rob day

 

But I think you should either preserve the tree structure or index of the layer? Otherwise, you won't be able to get a reference to specific layer?

 

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 03, 2024 Jun 03, 2024

Otherwise, you won't be able to get a reference to specific layer?

 

You could loop through the array and reference the layer by name:

 

 

 

 

var gl = app.activeDocument.selection[0].graphicLayerOptions.graphicLayers;
var ga = getAllGraphicLayers(gl);
for (var i = 0; i < ga.length; i++){
    if (ga[i].name == "Modelo" || ga[i].name == "Sombra") {
        ga[i].currentVisibility = false;
    } 
};   


/**
* Gets all of an image’s graphic layers as an array
* @ param the root graphic layer group 
* @ return an array of graphic layers 
*/
function getAllGraphicLayers(gl) {
    var gla = []
    for (var i = 0; i < gl.length; i++){
        if (gl[i].graphicLayers.length == 0) {
            gla.push(gl[i])
        } else if (gl[i].hasOwnProperty("graphicLayers")) {
            gla.push(gl[i])
            gla = gla.concat(getAllGraphicLayers(gl[i].graphicLayers));
            
        } 
    }; 
    if(gla.length){
        return gla
    }  
}

 

 

Screen Shot 3.png

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
LEGEND ,
Jun 03, 2024 Jun 03, 2024

@rob day

 

Yes, but if you do it like:

 

Edicao / Modelo

Edicao / Fundo / Circle

etc. 

 

You can show it directly to the user. 

 

It's also very easy to "decode" it in the script to get to the right group / layer.

 

No need to loop through the structure - you can just split, get number of elements in the array = know instantly how deep the layer is. 

 

Especially if you have a few groups & layers - and user selects last / deepest layer... 

 

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 04, 2024 Jun 04, 2024
LATEST

You can show it directly to the user.

 

I think @ril3ydx wants to dup and hide the shadow layer for 50 .PSDs, so there’s no dialog to show. Hard coding the path to the shadow layer works if you assume all of the layer trees are the same, but I wouldn‘t bet on that.

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