Skip to main content
Inspiring
February 18, 2022
Answered

Script to create smart object with layercomps from selected imageds in Bridge?

  • February 18, 2022
  • 5 replies
  • 1886 views

I'd love a script  for Photoshop or maybe for   Bridge directly   that would  make a number of selected images into  a single smart object with those images inside  and listed  as switchable  layercomps. 

 So for example  I could just select 4 images of a CG material:  color, normal map, spec map and height    and drop it as a single smart object in Photoshop  with all 4 made into layercomps inside  with same names .

 

Have anyone ever tried to do something like this?

This topic has been closed for replies.
Correct answer Stephen Marsh

This slightly modified version of the original script will allow the user to select multiple files in the standard Photoshop open dialog to create the stack:

 

/*
Selected files to smart object layer comps.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/script-to-create-smart-object-with-layercomps-from-selected-imageds-in-bridge/td-p/12760410
Stephen Marsh, v1.0
*/

#target photoshop

(function () {
    var savedDisplayDialogs = app.displayDialogs;
    app.displayDialogs = DialogModes.NO;
    var origUnits = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.PIXELS;

    var inputFiles = File.openDialog("Please select the files to stack:", Multiselect = true);
    if (inputFiles === null) {
        app.beep();
        return;
    }
    // inputFiles.sort().reverse;
    inputFiles.sort();

    app.displayDialogs = DialogModes.NO;

    var baseDoc = open(inputFiles[0]);
    var baseDoc = app.activeDocument;
    baseDoc.flatten();
    baseDoc.duplicate("Stacker", false);
    baseDoc.close(SaveOptions.DONOTSAVECHANGES);

    for (var i = 0; i < inputFiles.length; i++) {
        placeFile(new File(inputFiles[i]), true, 0, 0);
    }

    app.activeDocument.activeLayer = app.activeDocument.backgroundLayer;
    app.activeDocument.activeLayer.remove();

    revealAll();
    //align2SelectAll('AdCH');
    //align2SelectAll('AdCV');
    app.runMenuItem(stringIDToTypeID("selectAllLayers"));

    createSmartObject();
    app.activeDocument.activeLayer.name = 'Layer Comp Stack';
    app.runMenuItem(stringIDToTypeID('placedLayerEditContents'));

    for (var i = 0; i < app.activeDocument.layers.length; i++) {
        for (var j = 0; j < app.activeDocument.layers.length; j++) {
            app.activeDocument.layers[j].visible = false;
        }
        var layerIndex = i;
        app.activeDocument.layers[layerIndex].visible = true;
        var compName = app.activeDocument.layers[layerIndex].name;
        app.activeDocument.layerComps.add(compName, undefined, true, false, true, true);
        // Need to add a close step that actually saves the layer comps into the PSB! 
        var idsave = stringIDToTypeID( "save" );
        executeAction(idsave, undefined, DialogModes.NO);
    }

    //app.runMenuItem(stringIDToTypeID("selectAllLayers"));
    //reverseLayerStack();
    app.beep();
    app.displayDialogs = savedDisplayDialogs;
    app.preferences.rulerUnits = origUnits;


    // Functions

    function revealAll() {
        var s2t = function (s) {
            return app.stringIDToTypeID(s);
        };
        var descriptor = new ActionDescriptor();
        executeAction(s2t('revealAll'), descriptor, DialogModes.NO);
    }

    function createSmartObject() {
        try {
            var id325 = stringIDToTypeID("newPlacedLayer");
            executeAction(id325, undefined, DialogModes.NO);
        } catch (e) {
            alert("Error: Failed to make smart object " + e)
        }
    }

    function placeFile(null2, linked, horizontal, vertical) {
        var s2t = function (s) {
            return app.stringIDToTypeID(s);
        };
        var AD = new ActionDescriptor();
        AD.putInteger(s2t("ID"), 1);
        AD.putPath(s2t("null"), null2);
        AD.putBoolean(s2t("linked"), linked); // false for embedded
        AD.putEnumerated(s2t("freeTransformCenterState"), s2t("quadCenterState"), s2t("QCSAverage"));
        AD.putUnitDouble(s2t("horizontal"), s2t("pixelsUnit"), horizontal);
        AD.putUnitDouble(s2t("vertical"), s2t("pixelsUnit"), vertical);
        AD.putObject(s2t("offset"), s2t("offset"), AD);
        executeAction(s2t("placeEvent"), AD, DialogModes.NO);
    }

    function reverseLayerStack() {
        var idreverse = stringIDToTypeID("reverse");
        var desc4653 = new ActionDescriptor();
        var idnull = stringIDToTypeID("null");
        var ref2335 = new ActionReference();
        var idlayer = stringIDToTypeID("layer");
        var idordinal = stringIDToTypeID("ordinal");
        var idtargetEnum = stringIDToTypeID("targetEnum");
        ref2335.putEnumerated(idlayer, idordinal, idtargetEnum);
        desc4653.putReference(idnull, ref2335);
        executeAction(idreverse, desc4653, DialogModes.NO);
    }

    function align2SelectAll(method) {
        /*
        AdLf = Align Left
        AdRg = Align Right
        AdCH = Align Centre Horizontal
        AdTp = Align Top
        AdBt = Align Bottom
        AdCV = Align Centre Vertical
        */
        app.activeDocument.selection.selectAll();
        var desc = new ActionDescriptor();
        var ref = new ActionReference();
        ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
        desc.putReference(charIDToTypeID("null"), ref);
        desc.putEnumerated(charIDToTypeID("Usng"), charIDToTypeID("ADSt"), charIDToTypeID(method));
        try {
            executeAction(charIDToTypeID("Algn"), desc, DialogModes.NO);
        } catch (e) {}
        app.activeDocument.selection.deselect();
    }
})();

 

 

5 replies

c.pfaffenbichler
Community Expert
Community Expert
February 21, 2022

This would create copies and apply the Layer Comps to a Smart Object.

// create instances of smart object and apply all layer comps;
// 2022, use it at your own risk;
if (app.documents.length > 0) {
var ref = new ActionReference();	
ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
var layerDesc = executeActionGet(ref);
if (layerDesc.hasKey(stringIDToTypeID("smartObject")) == true) {
var theSO = layerDesc.getObjectValue(stringIDToTypeID("smartObject"));
var x = theSO.getList(stringIDToTypeID("compsList"));
var theCompsList = theSO.getObjectValue(stringIDToTypeID("compsList"));
if (theCompsList.count > 2) {
var theCompsList = theCompsList.getList(stringIDToTypeID("compList"));
var theSOComps = new Array;
for (var m = 0; m < theCompsList.count; m++) {
var thisOne = theCompsList.getObjectValue(m);
var theName = thisOne.getString(stringIDToTypeID("name"));
var theID = thisOne.getInteger(stringIDToTypeID("ID"));
var theComment = thisOne.getString(stringIDToTypeID("comment"));
theSOComps.push([theName, theID, theComment])
};
var theSOMore = layerDesc.getObjectValue(stringIDToTypeID("smartObjectMore"));
var appliedComp = theSOMore.getInteger(stringIDToTypeID("comp"));
// create copies and applylayercomp;
for (var n = 0;n < theSOComps.length;n++) {
    var thisComp = theSOComps[n];
    if (appliedComp != thisComp[1]) {
        executeAction( charIDToTypeID( "CpTL" ), undefined, DialogModes.NO );
        applyLayerCompToSmartObject(thisComp[1])
    }
}
}
}
};
////// apply layercomp to smart object //////
function applyLayerCompToSmartObject (theID) {
    // =======================================================
        var desc9 = new ActionDescriptor();
            var ref3 = new ActionReference();
            ref3.putEnumerated(charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ));
        desc9.putReference( charIDToTypeID( "null" ), ref3 );
        desc9.putInteger( stringIDToTypeID( "compID" ), theID );
    executeAction( stringIDToTypeID( "setPlacedLayerComp" ), desc9, DialogModes.NO );
    };
kirkr5689Author
Inspiring
February 21, 2022

c.pfaffenbichler

Thanks. but I couldn't seem to  figure out how to use it. Coudld you explain please.  Nothing happens  after I  run the script

c.pfaffenbichler
Community Expert
Community Expert
February 21, 2022

Is the active Layer a Smart Object that has Layer Comps? 

If not then nothing is supposed to happen. 

If the active Layer is a Smart Object with Layer Comps, then it should get copied as many times as necessary to apply all Layer Comps and those appied to the instances. 

 

I thought that was part of the original idea. 

Stephen Marsh
Community Expert
Stephen MarshCommunity ExpertCorrect answer
Community Expert
February 19, 2022

This slightly modified version of the original script will allow the user to select multiple files in the standard Photoshop open dialog to create the stack:

 

/*
Selected files to smart object layer comps.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/script-to-create-smart-object-with-layercomps-from-selected-imageds-in-bridge/td-p/12760410
Stephen Marsh, v1.0
*/

#target photoshop

(function () {
    var savedDisplayDialogs = app.displayDialogs;
    app.displayDialogs = DialogModes.NO;
    var origUnits = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.PIXELS;

    var inputFiles = File.openDialog("Please select the files to stack:", Multiselect = true);
    if (inputFiles === null) {
        app.beep();
        return;
    }
    // inputFiles.sort().reverse;
    inputFiles.sort();

    app.displayDialogs = DialogModes.NO;

    var baseDoc = open(inputFiles[0]);
    var baseDoc = app.activeDocument;
    baseDoc.flatten();
    baseDoc.duplicate("Stacker", false);
    baseDoc.close(SaveOptions.DONOTSAVECHANGES);

    for (var i = 0; i < inputFiles.length; i++) {
        placeFile(new File(inputFiles[i]), true, 0, 0);
    }

    app.activeDocument.activeLayer = app.activeDocument.backgroundLayer;
    app.activeDocument.activeLayer.remove();

    revealAll();
    //align2SelectAll('AdCH');
    //align2SelectAll('AdCV');
    app.runMenuItem(stringIDToTypeID("selectAllLayers"));

    createSmartObject();
    app.activeDocument.activeLayer.name = 'Layer Comp Stack';
    app.runMenuItem(stringIDToTypeID('placedLayerEditContents'));

    for (var i = 0; i < app.activeDocument.layers.length; i++) {
        for (var j = 0; j < app.activeDocument.layers.length; j++) {
            app.activeDocument.layers[j].visible = false;
        }
        var layerIndex = i;
        app.activeDocument.layers[layerIndex].visible = true;
        var compName = app.activeDocument.layers[layerIndex].name;
        app.activeDocument.layerComps.add(compName, undefined, true, false, true, true);
        // Need to add a close step that actually saves the layer comps into the PSB! 
        var idsave = stringIDToTypeID( "save" );
        executeAction(idsave, undefined, DialogModes.NO);
    }

    //app.runMenuItem(stringIDToTypeID("selectAllLayers"));
    //reverseLayerStack();
    app.beep();
    app.displayDialogs = savedDisplayDialogs;
    app.preferences.rulerUnits = origUnits;


    // Functions

    function revealAll() {
        var s2t = function (s) {
            return app.stringIDToTypeID(s);
        };
        var descriptor = new ActionDescriptor();
        executeAction(s2t('revealAll'), descriptor, DialogModes.NO);
    }

    function createSmartObject() {
        try {
            var id325 = stringIDToTypeID("newPlacedLayer");
            executeAction(id325, undefined, DialogModes.NO);
        } catch (e) {
            alert("Error: Failed to make smart object " + e)
        }
    }

    function placeFile(null2, linked, horizontal, vertical) {
        var s2t = function (s) {
            return app.stringIDToTypeID(s);
        };
        var AD = new ActionDescriptor();
        AD.putInteger(s2t("ID"), 1);
        AD.putPath(s2t("null"), null2);
        AD.putBoolean(s2t("linked"), linked); // false for embedded
        AD.putEnumerated(s2t("freeTransformCenterState"), s2t("quadCenterState"), s2t("QCSAverage"));
        AD.putUnitDouble(s2t("horizontal"), s2t("pixelsUnit"), horizontal);
        AD.putUnitDouble(s2t("vertical"), s2t("pixelsUnit"), vertical);
        AD.putObject(s2t("offset"), s2t("offset"), AD);
        executeAction(s2t("placeEvent"), AD, DialogModes.NO);
    }

    function reverseLayerStack() {
        var idreverse = stringIDToTypeID("reverse");
        var desc4653 = new ActionDescriptor();
        var idnull = stringIDToTypeID("null");
        var ref2335 = new ActionReference();
        var idlayer = stringIDToTypeID("layer");
        var idordinal = stringIDToTypeID("ordinal");
        var idtargetEnum = stringIDToTypeID("targetEnum");
        ref2335.putEnumerated(idlayer, idordinal, idtargetEnum);
        desc4653.putReference(idnull, ref2335);
        executeAction(idreverse, desc4653, DialogModes.NO);
    }

    function align2SelectAll(method) {
        /*
        AdLf = Align Left
        AdRg = Align Right
        AdCH = Align Centre Horizontal
        AdTp = Align Top
        AdBt = Align Bottom
        AdCV = Align Centre Vertical
        */
        app.activeDocument.selection.selectAll();
        var desc = new ActionDescriptor();
        var ref = new ActionReference();
        ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
        desc.putReference(charIDToTypeID("null"), ref);
        desc.putEnumerated(charIDToTypeID("Usng"), charIDToTypeID("ADSt"), charIDToTypeID(method));
        try {
            executeAction(charIDToTypeID("Algn"), desc, DialogModes.NO);
        } catch (e) {}
        app.activeDocument.selection.deselect();
    }
})();

 

 

kirkr5689Author
Inspiring
February 21, 2022

Thanks  you very much  Stephen .   Works perfect.    Now  would be super cool if we could start it from selection files in Bridge

Stephen Marsh
Community Expert
Community Expert
February 21, 2022

@kirkr5689 wrote:

Thanks  you very much  Stephen .   Works perfect.    Now  would be super cool if we could start it from selection files in Bridge


 

Thanks.

 

Easier said than done (for me).

 

Stephen Marsh
Community Expert
Community Expert
February 19, 2022

This Photoshop script will stack all files from the selected folder to a new file named "Stacker" with a single parent smart object layer with linked smart object child layers and layer comps named after the layers.

 

/*
Image folder files to smart object layer comps.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/script-to-create-smart-object-with-layercomps-from-selected-imageds-in-bridge/td-p/12760410
Stephen Marsh, v1.0
*/

#target photoshop

(function () {
    var savedDisplayDialogs = app.displayDialogs;
    app.displayDialogs = DialogModes.NO;
    var origUnits = app.preferences.rulerUnits;
    app.preferences.rulerUnits = Units.PIXELS;

    var inputFolder = Folder.selectDialog('Please select the input folder:');
    if (inputFolder === null) {
        app.beep();
        return;
    }

    var inputFiles = inputFolder.getFiles(/\.(jpg|jpeg|tif|tiff|png|psd|psb|gif)$/i);
    // inputFiles.sort().reverse;
    inputFiles.sort();

    app.displayDialogs = DialogModes.NO;

    var baseDoc = open(inputFiles[0]);
    var baseDoc = app.activeDocument;
    baseDoc.flatten();
    baseDoc.duplicate("Stacker", false);
    baseDoc.close(SaveOptions.DONOTSAVECHANGES);

    for (var i = 0; i < inputFiles.length; i++) {
        placeFile(new File(inputFiles[i]), true, 0, 0);
    }

    app.activeDocument.activeLayer = app.activeDocument.backgroundLayer;
    app.activeDocument.activeLayer.remove();

    revealAll();
    //align2SelectAll('AdCH');
    //align2SelectAll('AdCV');
    app.runMenuItem(stringIDToTypeID("selectAllLayers"));

    createSmartObject();
    app.activeDocument.activeLayer.name = 'Layer Comp Stack';
    app.runMenuItem(stringIDToTypeID('placedLayerEditContents'));

    for (var i = 0; i < app.activeDocument.layers.length; i++) {
        for (var j = 0; j < app.activeDocument.layers.length; j++) {
            app.activeDocument.layers[j].visible = false;
        }
        var layerIndex = i;
        app.activeDocument.layers[layerIndex].visible = true;
        var compName = app.activeDocument.layers[layerIndex].name;
        app.activeDocument.layerComps.add(compName, undefined, true, false, true, true);
        // Need to add a close step that actually saves the layer comps into the PSB! 
        var idsave = stringIDToTypeID( "save" );
        executeAction(idsave, undefined, DialogModes.NO);
    }

    //app.runMenuItem(stringIDToTypeID("selectAllLayers"));
    //reverseLayerStack();
    app.beep();
    app.displayDialogs = savedDisplayDialogs;
    app.preferences.rulerUnits = origUnits;


    // Functions

    function revealAll() {
        var s2t = function (s) {
            return app.stringIDToTypeID(s);
        };
        var descriptor = new ActionDescriptor();
        executeAction(s2t('revealAll'), descriptor, DialogModes.NO);
    }

    function createSmartObject() {
        try {
            var id325 = stringIDToTypeID("newPlacedLayer");
            executeAction(id325, undefined, DialogModes.NO);
        } catch (e) {
            alert("Error: Failed to make smart object " + e)
        }
    }

    function placeFile(null2, linked, horizontal, vertical) {
        var s2t = function (s) {
            return app.stringIDToTypeID(s);
        };
        var AD = new ActionDescriptor();
        AD.putInteger(s2t("ID"), 1);
        AD.putPath(s2t("null"), null2);
        AD.putBoolean(s2t("linked"), linked); // false for embedded
        AD.putEnumerated(s2t("freeTransformCenterState"), s2t("quadCenterState"), s2t("QCSAverage"));
        AD.putUnitDouble(s2t("horizontal"), s2t("pixelsUnit"), horizontal);
        AD.putUnitDouble(s2t("vertical"), s2t("pixelsUnit"), vertical);
        AD.putObject(s2t("offset"), s2t("offset"), AD);
        executeAction(s2t("placeEvent"), AD, DialogModes.NO);
    }

    function reverseLayerStack() {
        var idreverse = stringIDToTypeID("reverse");
        var desc4653 = new ActionDescriptor();
        var idnull = stringIDToTypeID("null");
        var ref2335 = new ActionReference();
        var idlayer = stringIDToTypeID("layer");
        var idordinal = stringIDToTypeID("ordinal");
        var idtargetEnum = stringIDToTypeID("targetEnum");
        ref2335.putEnumerated(idlayer, idordinal, idtargetEnum);
        desc4653.putReference(idnull, ref2335);
        executeAction(idreverse, desc4653, DialogModes.NO);
    }

    function align2SelectAll(method) {
        /*
        AdLf = Align Left
        AdRg = Align Right
        AdCH = Align Centre Horizontal
        AdTp = Align Top
        AdBt = Align Bottom
        AdCV = Align Centre Vertical
        */
        app.activeDocument.selection.selectAll();
        var desc = new ActionDescriptor();
        var ref = new ActionReference();
        ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
        desc.putReference(charIDToTypeID("null"), ref);
        desc.putEnumerated(charIDToTypeID("Usng"), charIDToTypeID("ADSt"), charIDToTypeID(method));
        try {
            executeAction(charIDToTypeID("Algn"), desc, DialogModes.NO);
        } catch (e) {}
        app.activeDocument.selection.deselect();
    }
})();

 

NOTE: Layer comps add filesize overhead, an alternative to comps would be to simply opt/alt click the layer visibility eye icon of the desired layer to make it visible while hiding the other layers.

 

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

Stephen Marsh
Community Expert
Community Expert
February 18, 2022

Just curious about the workflow? You obviously have to edit the smart object to change layer comp, I presume that you save and close to update with a new comp. What advantage does the comp offer in the workflow?

 

Can you provide screenshots to illustrate?

c.pfaffenbichler
Community Expert
Community Expert
February 18, 2022

If the renderings might need further work and get replaced later on I suspect using Linked Smart Objects might provide an alternative. 

kirkr5689Author
Inspiring
February 19, 2022

 

c.pfaffenbichler
Community Expert
Community Expert
February 18, 2022

Which part of the process is giving you problems?