Skip to main content
thomas_bredenfeld
Community Expert
Community Expert
January 22, 2024
Answered

Why is New Smart Object via Copy greyed out for linked Smart Objects?

  • January 22, 2024
  • 8 replies
  • 1334 views

When I have a Smart Object layer with linked file content, the menu option Layer > Smart Objects > New Smart Object via Copy isn't available. As this is a behavior in both PS 2023 and 2024 it looks like this is intentional. in this case: what's the reason for this? ... or is it simply a bug?

 

ps cc 2023 24.7.2
ps cc 2024 25.3.1
mac os x monterey 12.6.8

This topic is closed to new replies. Start a new post to keep the conversation going.
Correct answer Stephen Marsh

This command only applies to embedded smart objects. There is no way to break the relationship between an original and a copy for a linked file. It makes logical sense (for Photoshop) as this is a linked file. Smart objects have different behaviour than simpler linked files in Illustration or Layout software.

 

The command originated before linked smart objects were available. One could argue that it needs to be renamed to include the word embedded to clarify the intended use now that there are both linked and embedded options.

 

You can copy the linked smart object layer using another method and then use the "Convert to Smart Object" command, which will embed the previously linked layer. This isn't intuitive as it's already a smart object, again perhaps the command should now have the word embedded added to clarify what it does.

8 replies

Stephen Marsh
Community Expert
Community Expert
September 8, 2024

A new related script here:

 

https://community.adobe.com/t5/photoshop-ecosystem-discussions/please-fix-how-relink-to-file-and-replace-content-work/td-p/14846535

 

This script links to an existing file, rather than creating a new copy of the current linked file.

Stephen Marsh
Community Expert
Community Expert
January 27, 2024

This 1.1 script version will check if the new copy file exists and cancel the script without overwriting the file:

 

/*
New Linked Smart Object via Copy.jsx
v1.1 - 27th January 2024, Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/why-is-new-smart-object-via-copy-greyed-out-for-linked-smart-objects/td-p/14371680
NOTE: The script will automatically save a new linked copy of the original linked file adding " copy" to the name.
*/

#target photoshop

// Smart object action manager properties
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"));

// Conditional check for the active layer being a linked smart object
if (so.getBoolean(stringIDToTypeID("linked"))) {
// Single history stage undo
activeDocument.suspendHistory("New Linked Smart Object via Copy.jsx", "main()");
}


function main() {

// Doc path, name and extension variables
var thePath = so.getPath(stringIDToTypeID("link")).fullName.replace(/(^.+\/)(.*)/, '$1');
var theName = so.getString(stringIDToTypeID("fileReference")).replace(/\.[^\.]+$/, '');
var theExt = so.getString(stringIDToTypeID("fileReference")).replace(/(.+)(\.[^\.]+$)/, '$2');

// Duplicate the linked file adding copy to the name
var theCopy = new File(thePath + theName + " copy" + theExt);
if (!theCopy.exists) {
new File(thePath + theName + theExt).copy(thePath + theName + " copy" + theExt);
} else {
throw alert('File "' + thePath + theName + theExt + '" exists, script cancelled!');
//throw null;
}

// Set the reference to the original doc name
var origDocName = activeDocument.name;

// Dupe the smart object layer to a new temp doc
function s2t(s) {
return app.stringIDToTypeID(s);
}
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
var reference2 = new ActionReference();
reference.putClass(s2t("document"));
descriptor.putReference(s2t("null"), reference);
descriptor.putString(s2t("name"), "tempDoc");
reference2.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
descriptor.putReference(s2t("using"), reference2);
descriptor.putString(s2t("layerName"), activeDocument.activeLayer.name);
executeAction(s2t("make"), descriptor, DialogModes.NO);

// Relink to the duplicated file copy
var idplacedLayerRelinkToFile = stringIDToTypeID("placedLayerRelinkToFile");
var desc15 = new ActionDescriptor();
var idnull = stringIDToTypeID("null");
desc15.putPath(idnull, new File(thePath + theName + " copy" + theExt));
executeAction(idplacedLayerRelinkToFile, desc15, DialogModes.NO);

// Dupe the relinked temp doc layer back to the original doc
function s2t(s) {
return app.stringIDToTypeID(s);
}
var descriptor = new ActionDescriptor();
var reference3 = new ActionReference();
var reference4 = new ActionReference();
reference3.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
descriptor.putReference(s2t("null"), reference3);
reference4.putName(s2t("document"), origDocName);
descriptor.putReference(s2t("to"), reference4);
descriptor.putString(s2t("name"), activeDocument.activeLayer.name);
executeAction(s2t("duplicate"), descriptor, DialogModes.NO);
activeDocument.close(SaveOptions.DONOTSAVECHANGES);
}

 

 

An updated 1.2 script: Rather than cancelling the script if the new filename exists, the script will prompt for a new filename:
 

/*
New Linked Smart Object via Copy.jsx
Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/why-is-new-smart-object-via-copy-greyed-out-for-linked-smart-objects/td-p/14371680

v1.0 - 25th January 2024:
Initial release.

v1.1 - 27th January 2024:
Added filename validation so as not to overwrite an existing file.

v1.2 - 19th September 2026:
If the replacement file already exists, the user is prompted for a new name
(validated, re-prompted until valid) instead of the script cancelling.
Cancelling the prompt exits cleanly without changes.
*/

#target photoshop

// Smart object action manager properties
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"));

// Conditional check for the active layer being a linked smart object
if (so.getBoolean(stringIDToTypeID("linked"))) {
// Single history stage undo
activeDocument.suspendHistory("New Linked Smart Object via Copy.jsx", "main()");
}

function main() {

// Doc path, name and extension variables
var thePath = so.getPath(stringIDToTypeID("link")).fullName.replace(/(^.+\/)(.*)/, '$1');
var theName = so.getString(stringIDToTypeID("fileReference")).replace(/\.[^\.]+$/, '');
var theExt = so.getString(stringIDToTypeID("fileReference")).replace(/(.+)(\.[^\.]+$)/, '$2');

// Default copy filename
var copyName = theName + " copy";

// Check for filename clashes and allow the user to enter a new filename
var theCopy = new File(thePath + copyName + theExt);

if (theCopy.exists) {

var validName = false;

while (!validName) {

var newName = prompt(
'The file "' + copyName + theExt + '" already exists.\n\n' +
'Enter a new filename:',
copyName
);

// Cancel
if (newName === null) {
return;
}

// Remove leading/trailing spaces
newName = newName.replace(/^\s+|\s+$/g, '');

// Validate filename
if (newName === '') {
alert('Filename cannot be blank.');
continue;
}

// Remove extension if the user entered the original extension
var extRegex = new RegExp('\\' + theExt + '$', 'i');
if (extRegex.test(newName)) {
newName = newName.replace(extRegex, '');
}

// Check for invalid Windows filename characters
if (/[\\\/:\*\?"<>\|]/.test(newName)) {
alert(
'The filename contains invalid characters.\n\n' +
'The following characters are not allowed:\n' +
'\\ / : * ? " < > |'
);
continue;
}

// Prevent the new filename from matching the original
if (newName.toLowerCase() === theName.toLowerCase()) {
alert(
'The new filename cannot be the same as the original filename.'
);
continue;
}

// Check whether the new filename already exists
theCopy = new File(thePath + newName + theExt);

if (theCopy.exists) {
alert(
'The file "' + newName + theExt + '" already exists.\n\n' +
'Please enter a different filename.'
);
copyName = newName;
continue;
}

// Filename is valid and available
copyName = newName;
validName = true;
}
}

// Final copy file
theCopy = new File(thePath + copyName + theExt);

// Duplicate the linked file
if (!new File(thePath + theName + theExt).copy(theCopy.fsName)) {
alert(
'Unable to create the copied file:\n\n' +
theCopy.fsName
);
return;
}

// Set the references to the original doc name and original layer ID
var origDocName = activeDocument.name;
var origLayerID = activeDocument.activeLayer.id;

// Attempt to unlock the layer before it is duplicated to the temp doc
try {
unlockActiveLayer();
} catch (e) {}

// Dupe the smart object layer to a new temp doc
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
var reference2 = new ActionReference();
reference.putClass(s2t("document"));
descriptor.putReference(s2t("null"), reference);
descriptor.putString(s2t("name"), "tempDoc");
reference2.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
descriptor.putReference(s2t("using"), reference2);
descriptor.putString(s2t("layerName"), activeDocument.activeLayer.name);
executeAction(s2t("make"), descriptor, DialogModes.NO);

// Relink to the duplicated file copy
var idplacedLayerRelinkToFile = stringIDToTypeID("placedLayerRelinkToFile");
var desc15 = new ActionDescriptor();
var idnull = stringIDToTypeID("null");
desc15.putPath(idnull, theCopy);
executeAction(idplacedLayerRelinkToFile, desc15, DialogModes.NO);

// Dupe the relinked temp doc layer back to the original doc
var descriptor2 = new ActionDescriptor();
var reference3 = new ActionReference();
var reference4 = new ActionReference();
reference3.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
descriptor2.putReference(s2t("null"), reference3);
reference4.putName(s2t("document"), origDocName);
descriptor2.putReference(s2t("to"), reference4);
descriptor2.putString(s2t("name"), activeDocument.activeLayer.name);
executeAction(s2t("duplicate"), descriptor2, DialogModes.NO);

// Close the temp doc (still the active doc), which returns focus to the original doc
activeDocument.close(SaveOptions.DONOTSAVECHANGES);

// The new relinked layer is now the active layer in the original doc, store its ID
var newLayerID = activeDocument.activeLayer.id;

// Select the original (previous) layer in the stack
try {
selectLayerByID(origLayerID);
} catch (e) {
alert('Unable to select the original layer:\n\n' + e.message);
return;
}

// Delete the now redundant original layer (already unlocked above)
try {
app.activeDocument.activeLayer.remove();
} catch (e) {
alert(
'Unable to delete the original layer. It may still be locked.\n\n' +
e.message
);
}

// Reselect the new relinked layer
try {
selectLayerByID(newLayerID);
} catch (e) {
// Selection is left as-is
}
}


///// Functions /////

function s2t(s) {
return app.stringIDToTypeID(s);
}

function selectLayerByID(id) {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putIdentifier(s2t("layer"), id);
desc.putReference(s2t("null"), ref);
desc.putBoolean(s2t("makeVisible"), false);
executeAction(s2t("select"), desc, DialogModes.NO);
}

function unlockActiveLayer() {
var lyr = activeDocument.activeLayer;
var locked = false;

try {
if (lyr.allLocked || lyr.pixelsLocked || lyr.positionLocked || lyr.transparentPixelsLocked) {
locked = true;
}
} catch (e) {
// Lock state could not be read, attempt the unlock anyway
locked = true;
}

if (!locked) {
return;
}

try {
lyr.allLocked = false;
} catch (e) {}
try {
lyr.pixelsLocked = false;
} catch (e) {}
try {
lyr.positionLocked = false;
} catch (e) {}
try {
lyr.transparentPixelsLocked = false;
} catch (e) {}
}

function deleteActiveLayer() {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
desc.putReference(s2t("null"), ref);
executeAction(s2t("delete"), desc, DialogModes.NO);
}

 

Stephen Marsh
Community Expert
Community Expert
January 25, 2024

The following script can be used to create a New Linked Smart Object via Copy, creating a copy of the original linked file and relinking it to the new file:

 

/*
New Linked Smart Object via Copy.jsx
v1.0 - 25th January 2024, Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/why-is-new-smart-object-via-copy-greyed-out-for-linked-smart-objects/td-p/14371680
CAUTION: The new copy file will overwrite an existing file of the same name! If the linked file was named "my-file.psd" the script will create a new file named "my-file copy.psd" which would overwrite an existing file of the same name.
*/

#target photoshop

// Smart object action manager properties
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"));

// Conditional check for the active layer being a linked smart object
if (so.getBoolean(stringIDToTypeID("linked"))) {
    // Single history stage undo
    activeDocument.suspendHistory("New Linked Smart Object via Copy.jsx", "main()");
}


function main() {

    // Doc path, name and extension variables
    var thePath = so.getPath(stringIDToTypeID("link")).fullName.replace(/(^.+\/)(.*)/, '$1');
    var theName = so.getString(stringIDToTypeID("fileReference")).replace(/\.[^\.]+$/, '');
    var theExt = so.getString(stringIDToTypeID("fileReference")).replace(/(.+)(\.[^\.]+$)/, '$2');

    // Duplicate the linked file adding copy to the name
    new File(thePath + theName + theExt).copy(thePath + theName + " copy" + theExt);

    // Set the reference to the original doc name
    var origDocName = activeDocument.name;

    // Dupe the smart object layer to a new temp doc
    function s2t(s) {
        return app.stringIDToTypeID(s);
    }
    var descriptor = new ActionDescriptor();
    var reference = new ActionReference();
    var reference2 = new ActionReference();
    reference.putClass(s2t("document"));
    descriptor.putReference(s2t("null"), reference);
    descriptor.putString(s2t("name"), "tempDoc");
    reference2.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
    descriptor.putReference(s2t("using"), reference2);
    descriptor.putString(s2t("layerName"), activeDocument.activeLayer.name);
    executeAction(s2t("make"), descriptor, DialogModes.NO);

    // Relink to the duplicated file copy
    var idplacedLayerRelinkToFile = stringIDToTypeID("placedLayerRelinkToFile");
    var desc15 = new ActionDescriptor();
    var idnull = stringIDToTypeID("null");
    desc15.putPath(idnull, new File(thePath + theName + " copy" + theExt));
    executeAction(idplacedLayerRelinkToFile, desc15, DialogModes.NO);

    // Dupe the relinked temp doc layer back to the original doc
    function s2t(s) {
        return app.stringIDToTypeID(s);
    }
    var descriptor = new ActionDescriptor();
    var reference3 = new ActionReference();
    var reference4 = new ActionReference();
    reference3.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
    descriptor.putReference(s2t("null"), reference3);
    reference4.putName(s2t("document"), origDocName);
    descriptor.putReference(s2t("to"), reference4);
    descriptor.putString(s2t("name"), activeDocument.activeLayer.name);
    executeAction(s2t("duplicate"), descriptor, DialogModes.NO);
    activeDocument.close(SaveOptions.DONOTSAVECHANGES);
}

 

CAUTION: The new copy file will overwrite an existing file of the same name! If the linked file was named "my-file.psd" the script will create a new file named "my-file copy.psd" which would overwrite an existing file of the same name.

 

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

Stephen Marsh
Community Expert
Community Expert
January 24, 2024

We're going to have to agree to disagree then :]

I'm not talking about use cases, I'm describing the difference between the two types of Smart Objects. A linked SO is fundamentally different to an embedded SO. Photoshop isn't InDesign, links work differently.

 

To break the link to the original, the linked file would need to be duplicated and relinked to the new separate file. It's still linked, just linked to a different file.

 

EDIT: This could of course be automated so that a duplicate file is created and relinked.

thomas_bredenfeld
Community Expert
Community Expert
January 24, 2024

".... There is no way to break the relationship between an original and a copy for a linked file. It makes logical sense as this is a linked file. ..."
here i disagree: what about a use case where you need to replicate a SMO, let's say with all having the same layer FX applied and then e.g. to reposition these copies in a file and then replace their linked content to different external files. this would be a use case where "New Smart Object via Copy" would absolutely make sense.
e.g. think of an SMO (with a drop shadow and a frame) with several copies containing different artworks to be placed separately on a gallery wall.

c.pfaffenbichler
Community Expert
Community Expert
January 24, 2024

As far as I am concerned the term »bug« seems utterly unfit for this issue. 

 

As @Stephen Marsh pointed out, the process could be automated. 

So if it is important to you you may want to create a Script for it. 

Stephen Marsh
Community Expert
Community Expert
January 25, 2024

Sorry, I posted in the wrong topic, please ignore!

Stephen Marsh
Community Expert
Stephen MarshCommunity ExpertCorrect answer
Community Expert
January 22, 2024

This command only applies to embedded smart objects. There is no way to break the relationship between an original and a copy for a linked file. It makes logical sense (for Photoshop) as this is a linked file. Smart objects have different behaviour than simpler linked files in Illustration or Layout software.

 

The command originated before linked smart objects were available. One could argue that it needs to be renamed to include the word embedded to clarify the intended use now that there are both linked and embedded options.

 

You can copy the linked smart object layer using another method and then use the "Convert to Smart Object" command, which will embed the previously linked layer. This isn't intuitive as it's already a smart object, again perhaps the command should now have the word embedded added to clarify what it does.