skip to Main Content

I have Photoshop CC2019 PSD document containing several smart objects that contains other smart objects that contains other smart objects. Some of these have linked layers. Normally, such images are not updated automatically (which is extremely annoying, Adobe!) but you have to manually update each of them once the linked image content has changed.

There is a .jsx script file named “Update All Modified Content.jsx” which auto-updates linked layers (PNG image in my case) but only if the smart object is in the top most document – that is no nested smart objects with linked layers are updated automatically.

My question is: does anyone know how to update the content of the above mentioned .jsx file so that it would auto-update all linked images across all the smart objects in PSD document including nested ones?

For those who care or would be willing to help updating the code here it is:

// Update all modified content
var idplacedLayerUpdateAllModified = stringIDToTypeID( "placedLayerUpdateAllModified" );
executeAction( idplacedLayerUpdateAllModified, undefined, DialogModes.NO );

2

Answers


  1. Chosen as BEST ANSWER

    So, after spending half a day with it I finally solved it myself. Here is the code:

    #target photoshop
    
    // SET INITIAL ACTIVE DOCUMENT
    var mainDocument = app.activeDocument;
    
    // SAVE THE DOCUMENT NAME FOR FUTURE USE
    var mainDocName = mainDocument.name;
    
    // RUN THE MAIN UPDATE FUNCTION
    mainDocument.suspendHistory("processAllSmartObjects", "autoupdateAllSmartObjects(mainDocument, 0)");
    
    // FINALLY SAVE THE MAIN DOCUMENT
    mainDocument.save();
    
    function autoupdateAllSmartObjects(theParent, prevVal) {
    
        // FUNCTION TO TEST IF SMARTOBJECT IS LINKED
        function isLinkedSO(obj) {
    
            var localFilePath = "";
            var ref = new ActionReference();
            ref.putIdentifier(charIDToTypeID('Lyr '), obj.id);
            var desc = executeActionGet(ref);
            var smObj = desc.getObjectValue(stringIDToTypeID('smartObject'));  
            var isLinked = false;
    
            // TEST IF IT HAS LINKED FILE
            try {
                var localFilePath = smObj.getPath(stringIDToTypeID('link'));
                isLinked = true;
    
            } catch(e) {
                //
            }
    
            return isLinked; 
        }
    
        // FUNCTION TO UPDATE LINKED SMART OBJECT 
        function doTheUpdate(LYR, stackNr) {
    
            // SET ACTIVE LAYER TO ACTUALY ITERATED ONE
            app.activeDocument.activeLayer = LYR;
    
            // RUN IN "SILENT" MODE
            app.displayDialogs = DialogModes.NO;
            var layer = app.activeDocument.activeLayer;
    
            // IF ACTIVE LAYER IS SMARTOBJECT
            if (layer.kind == "LayerKind.SMARTOBJECT") {
    
                //alert(layer);
    
                // OPEN THE SMARTOBJECT
                app.runMenuItem(stringIDToTypeID('placedLayerEditContents'));
    
                // DO THE ACTUAL FILE UPDATE
                var idplacedLayerUpdateAllModified = stringIDToTypeID( "placedLayerUpdateAllModified" );
                executeAction( idplacedLayerUpdateAllModified, undefined, DialogModes.NO);
    
                // IF IT IS NOT THE "CORE/MAIN" DOCUMENT
                if(stackNr > 0) {
    
                    // SAVE CHANGES (UPDATE) AND CLOSE IT
                    app.activeDocument.close(SaveOptions.SAVECHANGES);
                }
    
                // CONTINUE INSIDE THIS ACTIVE SMARTOBJECT
                autoupdateAllSmartObjects(app.activeDocument, stackNr);
            }
    
            return;
        }
    
        // FUNCTION TO PARSE GROUPS
        function parseGroup(LYR) {
    
            var groupLayers = LYR.layers;
    
            // IF GROUP IS NOT EMPTY
            if(groupLayers.length > 0) {
    
                // PARSE ALL LAYERS IN THE GROUP
                for (var i = groupLayers.length - 1; i >= 0; i--) {
    
                    var lyr = groupLayers[i];
    
                    // IF NOT LOCKED = NOT EDITABL:E
                    if(!lyr.allLocked) {
    
                        // YET ANOTHER GROUP?
                        if (lyr.typename == "LayerSet") {
    
                            // IF IT IS NOT EMPTY
                            if (lyr.layers.length > 0) {
    
                                // RE-RUN THE SCRIPT ANEW WITH THE SELECTED GROUP AS LAYERS SOURCE
                                autoupdateAllSmartObjects(lyr, 0);
                            }
    
                        // LAYERS
                        } else if (lyr.typename == "ArtLayer") {
    
                            // IF THE LAYER IS SMARTOBJECT
                            if (lyr.kind == LayerKind.SMARTOBJECT) {
    
                                // IF THE LAYER IS SET TO "visible" (THAT IS: NOT DISABLED)
                                if(lyr.visible){
    
                                    // TEST IF THE SMARTOBJECT IS ACTUALLY LINKED
                                    if(!isLinkedSO(lyr)) {
    
                                        // RUN THE UPDATE SUB-FUNCTION
                                        doTheUpdate(lyr, i);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    
        // PARSE ALL THE LAYERS
        for (var i = theParent.layers.length - 1 - prevVal; i >= 0; i--) {
    
            var theLayer = theParent.layers[i];
    
            // ONLY ArtLayers
            if (theLayer.typename == "ArtLayer") {
    
                // IF THE LAYER IS SMARTOBJECT
                if (theLayer.kind == LayerKind.SMARTOBJECT) {
    
                    // IF THE LAYER IS SET TO "visible" (THAT IS: NOT DISABLED)
                    if(theLayer.visible){
    
                        // TEST IF THE SMARTOBJECT IS ACTUALLY LINKED
                        if(!isLinkedSO(theLayer)){
    
                            // RUN THE UPDATE SUB-FUNCTION
                            doTheUpdate(theLayer, i);
    
                            // IF WE ARE AT THE LAST LAYER IN THE STACK AND IT IS NOT OUR MAIN DOCUMENT
                            if(i == 0 && app.activeDocument.name !== mainDocName) {
    
                                // SAVE CHANGES (UPDATE) AND CLOSE IT
                                app.activeDocument.close(SaveOptions.SAVECHANGES);
                            }
                        }
                    }
                }
    
            // ONLY Groups
            } else if (theLayer.typename == "LayerSet") {
    
                // RUN SUB-FUNCTION FOR GROUP PARSING
                parseGroup(theLayer);
    
            // ANYTHING ELSE
            } else {
    
                autoupdateAllSmartObjects(theLayer, m);
            }
        }
    
        return;
    };
    

  2. OP’s script works!! It was going in loops for me too but after some trial and error, I realised that my smart objects (SO) that are linked across artboards ( – e.g. if you change one SO, it changes on various artboards) – were the issue. I hid all such SO and it works.

    so basically, it only works for Smart Objects + copies made via ‘New smart object via copy’ NOT ‘duplicate layer’ / copypaste smart objects. If your work contains a ‘duplicate layer’ SO – it will break the script. You need to hide these objects ( or not work like that all together) before running the script

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search