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

Copying layer comp list/directory from one doc to another

Participant ,
Feb 09, 2024 Feb 09, 2024

Hi all,

 

Is there a way to copy the list of layer comps and paste into a fresh list? 

 

Next bigger question, can you access the Layer Comp list within a smart object, as seen in the properties panel, and copy that?

 

I have a script that that culls layers by name, and makes layer comps from that data.  Unfortumanetly those layer comps need to be copied to the main worker, not just inside the smart object.

 

Thanks for any guidance.

~Roy
TOPICS
Actions and scripting
414
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

correct answers 3 Correct answers

Community Expert , Feb 10, 2024 Feb 10, 2024

1) What do you mean? Please post meaningful screenshots including all pertinent Panels to clarify. 

2) One can assess the Layer Comps of a Smart Object, what do you mean by »copy«? 

Screenshot 2024-02-10 at 13.42.14.pngScreenshot 2024-02-10 at 13.42.36.png

 

// 2023, use it at your own risk;
if (app.documents.length > 0) {
var theThings = collectSmartObjectsWithLayerComps();
alert (theThings.length+" smart object instances with layer comps\n\n"+theThings.join("\n\n"));
};
////////////////////////////////////
////// collect smart objects, probably based on code by paul
...
Translate
Participant , Feb 10, 2024 Feb 10, 2024

c.pfaffenbichler

it's just the list.  And as Steven pointed out below, they do match, under the old conditions.  e.g. The smart object has 5 UI locales, EN, SP, IT, JP, FR.  The layer comp reflects those.  Clicking on the layer comp drives the visibility of the language.  Outside the layer compes, exsists the same layer comp list, EN, SP, IT, JP, FR. clicking on the layer comp outside of the Smart Object, will also change the language.  It's cool, I love it.  

 

However the classic 5 locales are no

...
Translate
Community Expert , Feb 11, 2024 Feb 11, 2024

Screenshot 2024-02-11 at 18.01.49.pngScreenshot 2024-02-11 at 18.02.00.png

 

// create layer comps for layer comps in smart object;
// 2024, use it at your own risk;
if (app.documents.length > 0) {
var myDocument = activeDocument;
// remove existing layer comps;
myDocument.layerComps.removeAll();
var theSmartObject = collectSmartObjectsLayerComps ();
// process layer comps;
for (var y = 0; y < theSmartObject[2].length; y++) {
var thisOne = theSmartObject[2][y];
applyLayerCompToSmartObject (theSmartObject[1], thisOne[1]);
createLayerComp (thisOne[0]);
}
};
////////////
...
Translate
Adobe
Community Expert ,
Feb 10, 2024 Feb 10, 2024

1) What do you mean? Please post meaningful screenshots including all pertinent Panels to clarify. 

2) One can assess the Layer Comps of a Smart Object, what do you mean by »copy«? 

Screenshot 2024-02-10 at 13.42.14.pngScreenshot 2024-02-10 at 13.42.36.png

 

// 2023, use it at your own risk;
if (app.documents.length > 0) {
var theThings = collectSmartObjectsWithLayerComps();
alert (theThings.length+" smart object instances with layer comps\n\n"+theThings.join("\n\n"));
};
////////////////////////////////////
////// 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 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, theSOComps])
    };
}
};
}
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
Community Expert ,
Feb 10, 2024 Feb 10, 2024

»what do you mean by »copy«?« may seem like a strange question. 

 

Let me elaborate:

What you described as »the Layer Comp list within a smart object, as seen in the properties panel, and copy that« is probably not the end-point of the intended automation process, because what good is the list in the clipboard? 

How do you intend to use that list subsequently? 

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 Beginner ,
Feb 10, 2024 Feb 10, 2024

exactly correct Steven.  


Just getting back to this thread. I have a functional modified script that exports layer comps to files. Great. The trick has been to drive a predefined layer comp list, inside a smart object with the same list outside of the smart object using the properties panel. Also good. 

 
For example. I have a tv screen, and there will be 20 localized welcome screens in a psd with layer comps. I bring in that psd into tv file as a smart object. I recreate that list of layer comps that are in the smart object with another list in the tv worker. Scripts and actions do the rest. 
 
Through the last few years that list of 20 locales has morphed and changed. I have new scripts that builds the layer comp list based on the name of the locales, but I wanted to copy that list and for the main worker. 
 
Just so you understand, there are 30 -50 unique UI screens with 1  to 27 locales. Doing it by hand is time consuming and prone to mistakes. So that’s the gist. 
L
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
Participant ,
Feb 10, 2024 Feb 10, 2024

c.pfaffenbichler

it's just the list.  And as Steven pointed out below, they do match, under the old conditions.  e.g. The smart object has 5 UI locales, EN, SP, IT, JP, FR.  The layer comp reflects those.  Clicking on the layer comp drives the visibility of the language.  Outside the layer compes, exsists the same layer comp list, EN, SP, IT, JP, FR. clicking on the layer comp outside of the Smart Object, will also change the language.  It's cool, I love it.  

 

However the classic 5 locales are now going to be augmented.  It could be 1 to 27 and in differing groupings, and different Locale Codes.  I have a script that looks for specific parts of the name, and builds a layer comp for that name, i.e. 20240210_JP_tv_features.png equales a layer comp JP. Because of the random way the files will be used, I can't predetrmine a fixed layer comp list in and out of the smart object.  

 

So copying the list.  Either by selecting the smart object and go to the properties panel, you can see all the layer comps held inside.  Can that list be copied, so that same list be rcreated outside in the worker.  You use Parent and child, but I'm not sure that metaphor works in that the smart object is a unique file (Child?), and the worker housing it is also a unique file (Parent?.). That's one possible option. The other is to reopen the smart object and copy the layer comp names as a source and build out the same list for the target doc.

 

The rest is built and functional.  And under the original set of locales was so fun to export.  

 

I wish I could post screen caps, but NDA reqs don't allow.  I did post something as I was fleshing this out a couple of years ago.  In fact you help to crack the final nut in this worklow. c.pfaffenbichler

 

https://community.adobe.com/t5/photoshop-ecosystem-discussions/script-or-action-to-sync-layer-comps-...

 

~Roy
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 ,
Feb 11, 2024 Feb 11, 2024

I am having problems with your description. 

Please provide a mockup-file to demonstrate the current state and the intended result. 

 

quote

Can that list be copied, so that same list be rcreated outside in the worker. 

What good would the list copied to the clipboard be? 

Have you tested the code I posted? 

It gives an alert of the Layer Comps of all Smart Objects (with Layer Comps) in a file, but that can naturally limited to the active Smart Object (for example) and the Array can then be processed. 

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 ,
Feb 10, 2024 Feb 10, 2024

@RoyBoySolorio Creating matching layer comps in the parent document would only seem to make sense if the child smart object contained the same named layers as the parent.

 

Can you post a screenshot of the parent doc's layers panel, and also a screenshot of the child smart object doc's layers 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
Community Expert ,
Feb 11, 2024 Feb 11, 2024

Screenshot 2024-02-11 at 18.01.49.pngScreenshot 2024-02-11 at 18.02.00.png

 

// create layer comps for layer comps in smart object;
// 2024, use it at your own risk;
if (app.documents.length > 0) {
var myDocument = activeDocument;
// remove existing layer comps;
myDocument.layerComps.removeAll();
var theSmartObject = collectSmartObjectsLayerComps ();
// process layer comps;
for (var y = 0; y < theSmartObject[2].length; y++) {
var thisOne = theSmartObject[2][y];
applyLayerCompToSmartObject (theSmartObject[1], thisOne[1]);
createLayerComp (thisOne[0]);
}
};
////////////////////////////////////#
////// collect smart object’s layer comps, probably based on code by paul, mike or x //////
function collectSmartObjectsLayerComps () {
try {
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") ); 
//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'));
// is smart object;
if(layerDesc.hasKey(stringIDToTypeID('smartObject'))) {
// comps;
    var theSO = layerDesc.getObjectValue(stringIDToTypeID("smartObject"));
    var theCompsList = theSO.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 theCompName = thisOne.getString(stringIDToTypeID("name"));
    var theCompID = thisOne.getInteger(stringIDToTypeID("ID"));
    var theComment = thisOne.getString(stringIDToTypeID("comment"));
    theSOComps.push([theCompName, theCompID, theComment]);
    };
// add to array;
    return [theName, theID, theSOComps]
}
}
}
} catch (e) {};
};
////// apply layercomp to smart object //////
function applyLayerCompToSmartObject (theLayerID, theID) {
selectLayerByID(theLayerID, false);
    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 );
};
////// based on code by mike hale and paul riggott //////
function selectLayerByID(index,add){ 
add = undefined ? add = false:add 
var ref = new ActionReference();
    ref.putIdentifier(charIDToTypeID("Lyr "), index);
    var desc = new ActionDescriptor();
    desc.putReference(charIDToTypeID("null"), ref );
        if(add) desc.putEnumerated( stringIDToTypeID( "selectionModifier" ), stringIDToTypeID( "selectionModifierType" ), stringIDToTypeID( "addToSelection" ) ); 
        desc.putBoolean( charIDToTypeID( "MkVs" ), false ); 
    try{
    executeAction(charIDToTypeID("slct"), desc, DialogModes.NO );
}catch(e){
alert(e.message); 
}
};
////// create layer comp //////
function createLayerComp (theName) {
// =======================================================
var desc4 = new ActionDescriptor();
var ref2 = new ActionReference();
ref2.putClass( stringIDToTypeID( "compsClass" ) );
desc4.putReference( stringIDToTypeID( "null" ), ref2 );
var desc5 = new ActionDescriptor();
desc5.putBoolean( stringIDToTypeID( "useVisibility" ), true );
desc5.putBoolean( stringIDToTypeID( "usePosition" ), true );
desc5.putBoolean( stringIDToTypeID( "useAppearance" ), true );
desc5.putBoolean( stringIDToTypeID( "useChildLayerCompState" ), true );
desc5.putString( stringIDToTypeID( "title" ), theName );
var idcompsClass = stringIDToTypeID( "compsClass" );
desc4.putObject( stringIDToTypeID( "using" ), idcompsClass, desc5 );
executeAction( stringIDToTypeID( "make" ), desc4, DialogModes.NO );
};

edited

 

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
Participant ,
Feb 12, 2024 Feb 12, 2024
LATEST

Stunned and amazed c.pfaffenbichler.  

That was exactly what I needed.  Your screen grabs thru me off, but when I ran it, it made the list as needed, and did the syncing too. I'm updsting the actions and will beta test the new pipeline later today.  Thanks again for your help on this.  Maybe when complete I could send a training vid that shows the work inprogress.  Of course with prereleased assets.

~Roy
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