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

Determine Smart Object Attributes - Linked - Embedded - Missing - Path

Enthusiast ,
Jan 08, 2024 Jan 08, 2024

I've found a few older threads on Smart Objects, but none with a direct solution in this forum for getting smart object attributes.

Some of the older threads reference a try catch around placing a layer to determine if it's embedded:

 

        executeAction( stringIDToTypeID( "placedLayerConvertToEmbedded" ), undefined, DialogModes.NO );

 

 
I did find this thread on Stack Overflow, and am wondering if there are any other direct methods of getting info from a smart object.

https://stackoverflow.com/questions/63010107/get-a-smart-objects-layers-files-directory-source-in-js...

I've compiled a few separate scripts to determine the extension of the smart object, to evaluate if it's vector or raster.

Is there a more direct way to evaluate smart objects? I use script listener, but not well enough to understand how I can generate a true false value etc.
TOPICS
Actions and scripting
617
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
Adobe
Community Expert ,
Jan 08, 2024 Jan 08, 2024

From the same link:

 

// Check Test Get Property for Linked Smart Object.jsx

/* Based on:
https://stackoverflow.com/questions/63010107/get-a-smart-objects-layers-files-directory-source-in-jsx
*/

var ref = new ActionReference();
ref.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("smartObject"));
ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
var so = executeActionGet(ref).getObjectValue(stringIDToTypeID("smartObject"));

if (so.getBoolean(stringIDToTypeID("linked"))) {
  alert("Linked");
} else {
  alert("Embedded");
}
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 ,
Jan 08, 2024 Jan 08, 2024

Another one:

 

/*
https://stackoverflow.com/questions/63010107/get-a-smart-objects-layers-files-directory-source-in-jsx
*/

var mySO = getSmartObjectReference();

if (mySO.found) {
  alert('Is linked: ' + mySO.linked + '\nFile Name: ' + mySO.fileRef + '\nFile Path: ' + mySO.filePath);
}

function getSmartObjectReference()
{
  try
  {
    var smartObject = {
      found: false,
      fileRef: '',
      filePath: '',
      linked: false,
    };
    var ref, so;
    ref = new ActionReference();
    ref.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("smartObject"));
    ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
    so = executeActionGet(ref).getObjectValue(stringIDToTypeID("smartObject"));
    smartObject.found = true;
    smartObject.linked = so.getBoolean(stringIDToTypeID("linked"));
    smartObject.fileRef = so.getString(stringIDToTypeID("fileReference"));
    if (smartObject.linked) {
      smartObject.filePath = so.getPath(stringIDToTypeID("link"));
    } else {
      smartObject.filePath = Folder.temp + '/' + smartObject.fileRef;
    }
    return smartObject;
  }
  catch (e)
  {
    alert(e);
    return smartObject;
  }
}
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
Enthusiast ,
Jan 08, 2024 Jan 08, 2024

I've been using getSmartObjectReference(), wrapped in a loop that cycles through layers.

lyrSOInfo = getSmartObjectReference();
if(lyrSOInfo.filePath == '') alert("Linked File Is Missing")
if (lyrSOInfo.linked == true && lyrSOInfo.filePath != '') {
//Embed linked file
executeAction( stringIDToTypeID( "placedLayerConvertToEmbedded" ), undefined, DialogModes.NO );
}


By default it throws an error so I commented out alert(e), and I guess I could use found rather than testing the filePath directly.

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 ,
Jan 08, 2024 Jan 08, 2024

What do you actually want to achieve? 

Just a list of all linked SO, a list of the path’s of the linked files, …? 

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
Enthusiast ,
Jan 09, 2024 Jan 09, 2024

I'm evaluating each smart object in a file, and looking for something similar to InDesign's LinkStatus. When searching adobe forums, the tops hits that popped up were similar to the link/script below: https://community.adobe.com/t5/photoshop-ecosystem-discussions/file-information-for-smart-objects/m-...

Quoted from link:

var idplacedLayerConvertToEmbedded = stringIDToTypeID( "placedLayerConvertToEmbedded" );
executeAction( idplacedLayerConvertToEmbedded, undefined, DialogModes.NO );
theDoc.activeHistoryState = theDoc.historyStates[theDoc.historyStates.length-2];
alert ("linked")

 
getSmartObjectReference() works, but I wanted to ask on this forum as a recent answer also doesn't seem to be captured, at least the way I'm asking.

I'm using the link status/if statements to then trigger PS to embed linked Smart Objects.

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 ,
Jan 09, 2024 Jan 09, 2024

Your refer to a thread from 2014; SO’s AM-accessibility has been improved over time, so that does not seem useful. 

Have you seen this thread? 

https://community.adobe.com/t5/photoshop-ecosystem-ideas/is-there-an-option-that-shows-me-a-list-wit...

 

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 ,
Jan 09, 2024 Jan 09, 2024
quote

I'm evaluating each smart object in a file, and looking for something similar to InDesign's LinkStatus.

What do you actually mean? Please elaborate, post a meaningful screenshot/sketch … 

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
Enthusiast ,
Jan 09, 2024 Jan 09, 2024

Thanks for the link, I'll check it out.

Below is an excerpt of how I'm using the link status, since I've compiled from different scripts/functions it's not easy to show.

Please note, the below excerpts also utilize objectIsPsObject(SOlayer), in this script, but as it's lengthy I've omitted from this thread:
https://community.adobe.com/t5/photoshop-ecosystem-discussions/extendscript-photoshop-edit-contents-...

 

		//Layer can be set with a loop for each active layer
		layer = app.activeDocument.activeLayer;

                /******
		objectIsPsObject(layer) default determines as a raster smart object
		*******/
                if (layer.kind == LayerKind.SMARTOBJECT && objectIsPsObject(layer) == true) {
                    layer.rasterize(RasterizeType.ENTIRELAYER)
                }
                /******
                objectIsPsObject(layer) anything remaining is assumed a vector smart object and will be embedded or rasterized if missing
	        ******/
                if (layer.kind == LayerKind.SMARTOBJECT && objectIsPsObject(layer) == false) {
                    lyrSOStat = psGetSmartObjectReference();
                    //Check if file is linked, and if it is embed it
                    //Must check that the file path is not empty or it will error out when trying to embed
                    if (lyrSOStat.linked == true && lyrSOStat.filePath != '') executeAction( stringIDToTypeID( "placedLayerConvertToEmbedded" ), undefined, DialogModes.NO); 
                    //If FilePath is missing, rasterize the layer
                    if (lyrSOStat.filePath == '') layer.rasterize(RasterizeType.ENTIRELAYER);
                }

 

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 ,
Jan 09, 2024 Jan 09, 2024

Will you please tell me what you actually want to achieve

A dialog with the information, text in the clipboard, a Panel, …? 

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
Enthusiast ,
Jan 09, 2024 Jan 09, 2024

Sorry for any confusion, I'm just asking if there is a more direct way to get link statuses for smart objects within a script and then run a function based on that.

In Indesign, there are 5 statuses LinkStatus.LINK_MISSING, LinkStatus.LINK_OUT_OF_DATE, LinkStatus.LINK_INACCESSIBLE, LinkStatus.LINK_EMBEDDED, and LinkStatus.NORMAL. I was asking to see if there is a photoshop equivalent.

I have yet to review the link you sent, though I did see the stack overflow link in there as well. Thanks again.

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 ,
Jan 10, 2024 Jan 10, 2024
LATEST

Screenshot 2024-01-10 at 13.51.21.pngexpand image

// 2024, use it at your own risk;
if (app.documents.length > 0) {
var theThings = collectSmartObjectsWithLayerComps();
var theString = "smart objects are";
for (var m = 0; m < theThings.length; m++) {
    var thisOne = theThings[m];
    theString = theString + "\n\n" + thisOne[0] + "\nis linked: " + thisOne[1]; 
    if (thisOne[1] == true) {theString = theString + "\nlink missing: " + thisOne[2] + "\nlink changed; " + thisOne[3]}
};
alert (theString);
};
////////////////////////////////////
////// collect smart objects, probably based on code by paul, mike or x //////
function collectSmartObjectsWithLayerComps () {
// 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'))) {
    var soDesc = layerDesc.getObjectValue(stringIDToTypeID('smartObject'));
    var theFileRef = soDesc.getString(stringIDToTypeID('fileReference'));
    var theDocID = soDesc.getString(stringIDToTypeID('documentID'));
    var isLinked = soDesc.getBoolean(stringIDToTypeID('linked'));
    if (isLinked == true) {
    var isMissing = soDesc.getBoolean(stringIDToTypeID('linkMissing'));
    var isChanged = soDesc.getBoolean(stringIDToTypeID('linkChanged'));
    } else {
    var isMissing = undefined;
    var isChanged = undefined;
    };
    /*var x = soDesc.getList(stringIDToTypeID("compsList"));
    var theCompsList = soDesc.getObjectValue(stringIDToTypeID("compsList"));
    if (theCompsList.count > 2) {
        var theCompsList = theCompsList.getList(stringIDToTypeID("compList"));
        var theSOComps = new Array;
        for (var n = 0; n < theCompsList.count; n++) {
        var thisOne = theCompsList.getObjectValue(n);
        var compName = thisOne.getString(stringIDToTypeID("name"));
        var compID = thisOne.getInteger(stringIDToTypeID("ID"));
        var theComment = thisOne.getString(stringIDToTypeID("comment"));
        theSOComps.push([compName, compID, theComment]);
        };
        theLayers.push([theName, theID, theFileRef, theDocID])
        theLayers.push([theName, theID, theFileRef, theDocID, theSOComps])
    };*/
    theLayers.push([theName, isLinked, isMissing, isChanged, theID, theFileRef, theDocID])
}
}
}
catch (e) {};
};
return theLayers
};
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