Nested smart objects Auto-update 2022

Community Beginner ,
May 26, 2022 May 26, 2022

Copy link to clipboard

Copied

I'm creating tiles for a game engine.

I have a MASTER layout file into which I place linked external TILE psb files.

Each linked TILE file has inside it linked external TEXTURE psb files (so I can ensure all my base textures tile correctly)

 

As far as i can tell, if i change the TEXTURE tile, i have to manually open every TILE file and updated the modified content, then open the MASTER file and update all the modified content.

 

Is thewre any way for the MASTER file when opening to check the modified nested structure and update by itself? And if not could Adobe add such a function?

TOPICS
Actions and scripting , macOS , Windows

Views

168

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
May 26, 2022 May 26, 2022

Copy link to clipboard

Copied

You are correct in that it does work that way.

 

I wonder though if a script could be written to open each and update? I am no expert in scripting though, so have tagged a couple of folk who are:   @jazz-y  @Stephen_A_Marsh 

 

Dave

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
May 27, 2022 May 27, 2022

Copy link to clipboard

Copied

If I am understanding the "Russian Doll" issue, then yes, I believe that a script can handle this... Even better, I believe that it is within my capabilities!

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
May 27, 2022 May 27, 2022

Copy link to clipboard

Copied

Yes that is how it works on multiple files. Look into Layer comps, they are a great way to have one master file to create multiple files in a series. 

 

With layer comps use file >> Export >> Layer Comps To files to generate your files.

 

Another way taht shdou work is to drag a layer to your library. Later after adding the library item to your files or Russian doll, edit the library item by double clicking on the item in the library.

Likes

Translate

Translate

Report

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 30, 2022 May 30, 2022

Copy link to clipboard

Copied

Thanks Mike, i did get the script method working, but the library method sounds promising as well. One reason we avoid photoshop libraries (in our company) is that we use an SVN to commit and version projects so have always tried to avoid being tied to a users library.. maybe there's a way to keep the project library as a local foldered version?

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
May 27, 2022 May 27, 2022

Copy link to clipboard

Copied

@Gravois – The following script will update linked files within linked files, so only 2 levels deep. I have tested it and I believe that it meets your criteria. Let me know how it goes for you...

 

/*
Update linked layers inside linked layers.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/nested-smart-objects-auto-update-2022/m-p/12968009
Stephen Marsh, 28th May 2022, Version 1.0
With special thanks to Christoph Pfaffenbichler for the recursive SO processing framework:
https://feedback.photoshop.com/photoshop_family/topics/rasterize_all_smart_objects_in_a_psd_file_to_shrink_down_its_size
*/

#target photoshop

var myDocument = app.activeDocument;
myDocument.suspendHistory("processAllSmartObjects", "processSOLayers(myDocument)");

processSOLayers(theLayer);

function processSOLayers(docLayers) {

    var restoreDialogMode = app.displayDialogs;
    app.displayDialogs = DialogModes.NO;

    // Loop over all the layers
    for (var i = docLayers.layers.length - 1; i >= 0; i--) {
        var theLayer = docLayers.layers[i];

        // Only run on smart object layers
        if (theLayer.typename === "ArtLayer" && theLayer.kind === LayerKind.SMARTOBJECT) {
                var theVisibility = theLayer.visible;
                myDocument.activeLayer = theLayer;

                // Edit the linked smart object layer
                app.runMenuItem(stringIDToTypeID('placedLayerEditContents'));
                // Update all modified content
                app.runMenuItem(stringIDToTypeID('placedLayerUpdateAllModified'));
                // Close and save
                app.activeDocument.close(SaveOptions.SAVECHANGES);

                // Reset visibility; 
                theLayer.visible = theVisibility;

        // Run on the contents of layerSets (implied, not explicitly defined)
        } else {
            processSOLayers(theLayer);
        }
    }
    
    app.displayDialogs = restoreDialogMode;
    
    return;
}

 

  1. Copy the code text to the clipboard
  2. Open a new blank file in a plain-text editor (not in a word processor)
  3. Paste the code in
  4. Save the text file as .txt
  5. Rename the file extension from .txt to .jsx
  6. Install or browse to the .jsx file to run:

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

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
May 28, 2022 May 28, 2022

Copy link to clipboard

Copied

@Stephen_A_Marsh  Thanks Stephen 🙂

Dave

Likes

Translate

Translate

Report

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 30, 2022 May 30, 2022

Copy link to clipboard

Copied

Hi @Stephen_A_Marsh thankyou for helping. The script works as long as I remove all other non-linked smart objects. Is there a way to ammend the script so that it can ignore normal smart embedded smart objects or bg layers? or should every item (such as non-tiling assets) be stored as externally linked objects as well?

 

thankyou very much for your help.

 

 

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
May 30, 2022 May 30, 2022

Copy link to clipboard

Copied


@Gravois wrote:

Hi @Stephen_A_Marsh thankyou for helping. The script works as long as I remove all other non-linked smart objects. Is there a way to ammend the script so that it can ignore normal smart embedded smart objects or bg layers? or should every item (such as non-tiling assets) be stored as externally linked objects as well?

 

thankyou very much for your help.


 

Ah, your OP only mentioned linked smart objects, not a mixture of linked and embedded. Of course, I didn't test for that! :]

 

There is a conditional in there to only process smart object layers, however, I'll have to find out a way to differentiate between linked vs. embedded, off-hand I don't know of a property for that.

 

@c.pfaffenbichler – I borrowed the smart object code from one of your scripts, do you know of a property or hack to isolate linked from embedded?

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
May 30, 2022 May 30, 2022

Copy link to clipboard

Copied

The easiest way would probably be wrapping the updating-line into a try-clause. 

 

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
May 31, 2022 May 31, 2022

Copy link to clipboard

Copied

@c.pfaffenbichler – I couldn't get that to work, however, I did find some code from @r-bin that appears do what I originally wanted.

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
May 31, 2022 May 31, 2022

Copy link to clipboard

Copied

Depending on the number of Smart Objects addressing them via DOM might take a bit long-ish. 

Switching to AM-code could offer some advantages speed-wise, but I am not sure whether it’s worth the trouble. 

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
May 31, 2022 May 31, 2022

Copy link to clipboard

Copied

I guess that this is always the case, the more layers the longer the for loops take. The challenge is twofold (for me):

 

1) Finding suitable examples of AM code

2) Understanding them, extracting the code and making it generic or usable in other scripts

 

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
Jun 01, 2022 Jun 01, 2022

Copy link to clipboard

Copied

Here is an example to collect Smart Objects. 

// 2017, use it at your own risk;
if (app.documents.length > 0) {
alert (collectSmartObjects2017().join("\n"));
};
////////////////////////////////////
////// collect smart objects, probably based on code by paul, mike or x //////
function collectSmartObjects2017 () {
// the file;
var myDocument = app.activeDocument;
// get number of layers;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
var theLayers = new Array;
for (var m = 0; m <= theNumber; m++) {
try {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), m);
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// if not layer group collect values;
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart" && isBackground != true) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
if(layerDesc.hasKey(stringIDToTypeID('smartObject'))) {theLayers.push([theName, theID])}
};
}
catch (e) {};
};
return theLayers
};

 

This one collects the paths of linked smart objects. 

// get list of linked smart objects’ paths;
// 2022, use it at your own risk;
var aaa = collectSmartObjectsLinks ();
alert ("\n"+aaa.join("\n\n"));
////// collect layers //////
function collectSmartObjectsLinks () {
// get number of layers;
var ref = new ActionReference();
ref.putProperty(stringIDToTypeID('property'), stringIDToTypeID('numberOfLayers'));
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
var theLayers = new Array;
for (var m = 0; m <= theNumber; m++) {
try {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), m);
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
var isSmartObject = layerDesc.hasKey(stringIDToTypeID("smartObject"));
// collect smart object links;
if (isSmartObject == true /*&& layerSet != "layerSectionEnd" && layerSet != "layerSectionStart" && isBackground != true*/) {
var theSO = layerDesc.getObjectValue(stringIDToTypeID("smartObject"));
if (theSO.getBoolean(stringIDToTypeID("linked")) == true) {
var theLink = theSO.getPath(stringIDToTypeID("link"));
var theCheck = true;
for (var n = 0; n < theLayers.length; n++) {
if (theLayers[n] == String(theLink)) {theCheck = false}
};
if (theCheck == true) {theLayers.push(theLink)};
};
};
}
catch (e) {};
};
return theLayers
};

 

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
Jun 02, 2022 Jun 02, 2022

Copy link to clipboard

Copied

LATEST

@Gravois – So, how did the revised 1.1 version script work for you?

Likes

Translate

Translate

Report

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
Adobe Community Professional ,
May 31, 2022 May 31, 2022

Copy link to clipboard

Copied

@Gravois 

 

Try this 1.1 version:

 

/*
Update linked layers inside linked layers v1-1.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/nested-smart-objects-auto-update-2022/m-p/12968009
Stephen Marsh, 31st May 2022, Version 1.1
*/

#target photoshop

var myDocument = app.activeDocument;
myDocument.suspendHistory("processAllSmartObjects", "processSOLayers(myDocument)");

function processSOLayers(docLayers) {
    // processSOLayers function courtesy of c.pfaffenbichler
    var restoreDialogMode = app.displayDialogs;
    app.displayDialogs = DialogModes.NO;
    // Loop over all the layers
    for (var i = docLayers.layers.length - 1; i >= 0; i--) {
        var theLayer = docLayers.layers[i];
        if (theLayer.typename === "ArtLayer") {
            var theVisibility = theLayer.visible;
            myDocument.activeLayer = theLayer;

            // Linked SO conditional check courtesy of r-bin
            var r = new ActionReference();
            r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("smartObject"));
            r.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
            var d = executeActionGet(r);
            if (d.hasKey(stringIDToTypeID("smartObject"))) {
                d = d.getObjectValue(stringIDToTypeID("smartObject"));
                if (d.hasKey(stringIDToTypeID("link"))) {

                    // Edit the linked smart object layer
                    app.runMenuItem(stringIDToTypeID('placedLayerEditContents'));
                    // Update all modified content
                    app.runMenuItem(stringIDToTypeID('placedLayerUpdateAllModified'));
                    // Close and save
                    app.activeDocument.close(SaveOptions.SAVECHANGES);

                }
            }

            // Reset visibility; 
            theLayer.visible = theVisibility;

            // Run on the contents of layerSets (implied, not explicitly defined)
        } else {
            processSOLayers(theLayer);
        }
    }

    app.displayDialogs = restoreDialogMode;

    return;
}

 

 

Likes

Translate

Translate

Report

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