Copy link to clipboard
Copied
Hi all,
I need just one last bit to complete an epic process. I have a multi language Smart Object embeded in a working psd. In the Smart Object is a Layer Comp that controls visibility of each language. Outside the Smart Object is the same Layer Comp list. Using the properties panel I can sync the two Layer Comps, controlling the language visibility. But it's a manual process.
When trying to build that behavior as an action using the "Next" button in the Layer Comp panel and the same named Layer Comp in the properties panel, I get an ID number. Which would be fine, except when tried on a new working psd. Then it's not recognized.
If it's helpful, both in and out Layer Comps have identical names i.e. EN, JA, SP, FR, DA, ZH in the same order starting with EN. Thanks in advance for any guidance.
I guess »Layer Comp Selection for Smart Objects« would have to be set in the Layer Comps in the containing document, but otherwise this might work:
// if smart object has layer comps with same names as containing document select them and ipdate containing doc’s comps;
// 2022, use it at your own risk;
if (app.documents.length > 0) {
var myDocument = activeDocument;
var theLayerComps = getLayerCompsArray ();
var theSmartObjects = collectSmartObjectsLayerComps ();
// process layer comps;
for (var
...
Copy link to clipboard
Copied
I do not understand what exactly is problem. Testing Apply next layer comp using action and it works just fine. Can you post some screenshot to clarify what exactly you are doing and what is the problem?
This sentence is esspecially confusing to me: "When trying to build that behavior as an action using the "Next" button in the Layer Comp panel and the same named Layer Comp in the properties panel, I get an ID number. "
Here is my take, assuming that you have PSD file with layer comps which is placed inside another file. Action looks like this:
Edit Contents (embedded smart object with layer comps must be selected, record step before for that if necessary)
Apply next layer comp
Close (Saving:yes)
Copy link to clipboard
Copied
My appologies, this is a complex workflow and I'm not sure a screen cap will do it. All this is for use with Export Layer Comps, which creates specific psds named per the layer comp. That part is fine.
There are two identical layer comp lists. One inside the embedded Smart object, EN, JA, NO. The other in the comp/working psd, EN, JA, NO. Again an Inside Layer Comp and Outside Layer Comp. To link the two I select "EN" Outside LC and via the Properties Panel go to the pull down menu and select the "EN" in the embedded LC, then sync/update the Outside layer comp. I can manually do that for all the flags. When done, selecting the "NO" layer comp, changes the embedded Smart Object to the "NO" flag, and so on.
Making an action to select the next Outside LC and selecting the corresponding embedded LC via the properties panel comes up with a ID number unique to that choice. The action fails on the next PSD.
Copy link to clipboard
Copied
You can change layer comp for current document then select and edith embedded PSD, change layer comp while in editing mode as shown in my screenshot above and deed will be done, if I can understand you. What is function of layer comps in document with one layer (embedded SO) only? I think you are overcomplicating without any need, if I do understand what are you trying to do. You can not export layer comps (File > Export > Layer Comps...) and isntruct Photoshop to change layer comp in embedded file for each layer comp in current document, at least I do not know for trick, especially using Photoshop actions.
Copy link to clipboard
Copied
My example is dumbed down and privacy concerns keep me from showing anything accurate The end ask is for hundreds of combinations between product and language localization.
Copy link to clipboard
Copied
And yes the export layer comp script does exactly that. It travels down the list of layer comps, adjusts the embedded layer comp as synced, then exports a separate file for each.
Copy link to clipboard
Copied
I have used layer comps to files few times but I do not understand what is actual problem, apologies.
Copy link to clipboard
Copied
@RoyBoySolorio wrote:
My example is dumbed down and privacy concerns keep me from showing anything accurate The end ask is for hundreds of combinations between product and language localization.
Then please provide a meaningful mock-up file.
Copy link to clipboard
Copied
Is there a way to post a psd to the forum? Or link?
Copy link to clipboard
Copied
Attached is a psd working file. It's been stripped down and renamed for security purposes. Pull up the Layer Comp and properties panels. Highlight the smart object. Clicking on the layer comp name or arrowing through, the properties panel drives the layer comp within the embedded smart object to change. Changing the image in the Smart Object.
To get that behavior to work you manually sync the two layer comps. I'm looking for an action/script to do that routine.
Copy link to clipboard
Copied
I downloaded and tested using your file. If you always have same layer comps, actually layer comps with same name in embedded file and you need exactly same layer comps in working document then the solution can be following:
Here is how it looks when recorded without ID but with hard coded layer comp names.
In case that you have layer comps with different names in each new file and you want to copy name and create new layer comp with the same name in the working document then I must inform you it is not possible using Photoshop action.
Copy link to clipboard
Copied
Thanks Bojan, I appreciate it but with the export layer comp system already established, entering an exiting the smart object doesn't flow with that. I keep looking around.
Copy link to clipboard
Copied
I do not understand what exactly you mean but let me try one more time. You have problem because there are already created layer comps in working file? Delete them , simply delete them for what you can record action steps. If you are always using same working file run same action with steps to delete existing layer comps then to open smart object and do things as shown above in screenshot with expanded action steps.
Copy link to clipboard
Copied
I guess »Layer Comp Selection for Smart Objects« would have to be set in the Layer Comps in the containing document, but otherwise this might work:
// if smart object has layer comps with same names as containing document select them and ipdate containing doc’s comps;
// 2022, use it at your own risk;
if (app.documents.length > 0) {
var myDocument = activeDocument;
var theLayerComps = getLayerCompsArray ();
var theSmartObjects = collectSmartObjectsLayerComps ();
// process layer comps;
for (var y = 0; y < theLayerComps.length; y++) {
var thisComp = theLayerComps[y];
for (var z = 0; z < theSmartObjects.length; z++) {
for (var x = 0; x < theSmartObjects[z][2].length; x++) {
var thisSOLC = theSmartObjects[z][2][x];
if (thisComp[0] == thisSOLC[0]) {
applyLayerComp (thisComp[2]);
applyLayerCompToSmartObject(theSmartObjects[z][1], thisSOLC[1]);
}
}
updateLayerComp ();
};
}
};
////////////////////////////////////#
////// collect smart objects, probably based on code by paul, mike or x //////
function collectSmartObjectsLayerComps () {
// 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'));
// 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;
theLayers.push([theName, theID, theSOComps])
}
}
}
} catch (e) {};
};
return theLayers
};
////// get array of layer comps’ properties //////
function getLayerCompsArray () {
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var docDesc = executeActionGet(ref);
var compList = docDesc.getList(stringIDToTypeID("compsList"));
var theComps = new Array;
for (var c = 0; c < compList.count; c++) {
var thisOne = compList.getObjectValue(c);
theComps.push(getObjectDesc(thisOne))
};
return theComps;
};
////// based on code by michael l hale //////
function getObjectDesc (theDesc) {
var c = theDesc.count;
var str = new Array;
for(var i=0;i<c;i++){ //enumerate descriptor's keys
// str.push([i+' = '+typeIDToStringID(theDesc.getKey(i))+': '+theDesc.getType(theDesc.getKey(i))+'\n'+getValues (theDesc, i)]);
str.push(getValues (theDesc, i));
};
return(str);
};
////// check //////
function getValues (theDesc, theNumber) {
switch (theDesc.getType(theDesc.getKey(theNumber))) {
case DescValueType.ALIASTYPE:
return theDesc.getPath(theDesc.getKey(theNumber));
break;
case DescValueType.BOOLEANTYPE:
return theDesc.getBoolean(theDesc.getKey(theNumber));
break;
case DescValueType.CLASSTYPE:
return theDesc.getClass(theDesc.getKey(theNumber));
break;
case DescValueType.DOUBLETYPE:
return theDesc.getDouble(theDesc.getKey(theNumber));
break;
case DescValueType.ENUMERATEDTYPE:
return (typeIDToStringID(theDesc.getEnumerationValue(theDesc.getKey(theNumber)))+"_"+typeIDToStringID(theDesc.getEnumerationType(theDesc.getKey(theNumber))));
break;
case DescValueType.INTEGERTYPE:
return theDesc.getInteger(theDesc.getKey(theNumber));
break;
case DescValueType.LISTTYPE:
return theDesc.getList(theDesc.getKey(theNumber));
break;
case DescValueType.OBJECTTYPE:
return (theDesc.getObjectValue(theDesc.getKey(theNumber))+"_"+typeIDToStringID(theDesc.getObjectType(theDesc.getKey(theNumber))));
break;
case DescValueType.RAWTYPE:
return theDesc.getReference(theDesc.getData(theNumber));
break;
case DescValueType.REFERENCETYPE:
return theDesc.getReference(theDesc.getKey(theNumber));
break;
case DescValueType.STRINGTYPE:
return theDesc.getString(theDesc.getKey(theNumber));
break;
case DescValueType.UNITDOUBLE:
return (theDesc.getUnitDoubleValue(theDesc.getKey(theNumber))+"_"+typeIDToStringID(theDesc.getUnitDoubleType(theDesc.getKey(theNumber))));
break;
default:
break;
};
};
////// apply layercomp to smart object //////
function applyLayerCompToSmartObject (theLayerID, theID) {
selectLayerByID(theLayerID, false);
var desc9 = new ActionDescriptor();
var ref3 = new ActionReference();
// ref3.putIdentifier(charIDToTypeID( "Lyr " ), theLayerID);
ref3.putEnumerated(charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ));
desc9.putReference( charIDToTypeID( "null" ), ref3 );
desc9.putInteger( stringIDToTypeID( "compID" ), theID );
executeAction( stringIDToTypeID( "setPlacedLayerComp" ), desc9, DialogModes.NO );
};
////// apply layer comp //////
function applyLayerComp (theID) {
// =======================================================
var desc6 = new ActionDescriptor();
var ref3 = new ActionReference();
ref3.putIdentifier( stringIDToTypeID( "compsClass" ), theID );
//ref3.putName( stringIDToTypeID( "compsClass" ), theName );
desc6.putReference( stringIDToTypeID( "null" ), ref3 );
executeAction( stringIDToTypeID( "applyComp" ), desc6, DialogModes.NO );
};
////// update layer comp //////
function updateLayerComp () {
var desc13 = new ActionDescriptor();
var ref8 = new ActionReference();
ref8.putEnumerated( stringIDToTypeID( "compsClass" ), stringIDToTypeID( "ordinal" ), stringIDToTypeID( "targetEnum" ) );
desc13.putReference( stringIDToTypeID( "null" ), ref8 );
executeAction( stringIDToTypeID( "recapture" ), desc13, 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);
}
};
Copy link to clipboard
Copied
Super excited to test this out. This last piece of the puzzle is the only
part that is done manually. I'll be checking it out Monday night.
I guess part of being so busy is because you're good at what you do. May I
ask, why do you help folks like me out, probably on your own time?
Regardless of the outcome here, I am extremely grateful for your gift.
Thank you.
Regards,
(personal info removed)
Copy link to clipboard
Copied
ABSOLUTLY BRILLIANT. Did exactly what I needed. Thank you, thank you.
Copy link to clipboard
Copied
May I ask, why do you help folks like me out, probably on your own time?
There is a proverb (or at least a a quote from a movie) – »If someone does you a favor, don’t pay it back, pass it on«.
People on this Forum (respectively its previous incarnations) have helped me in the past, so trying to help others in turn seems only fair.
And some Scripting tasks seem interesting to figure out …
Copy link to clipboard
Copied
@RoyBoySolorio wrote:
May I ask, why do you help folks like me out, probably on your own time?
Yes, @RoyBoySolorio if you can set aside some time to work on a mockup file, maybe record a video explaining how to use the script, so that it could reach and help more people?
Or feel free to stick around and reply to some threads, help others in return!
Do something kind to a stranger, there are so many ways to make this world a better place...
Copy link to clipboard
Copied
In my excitement I replied to myself on this. c.pfaffenbichler you nailed it. I state it here too ABSOLUTELY BRILLIANT!!
Copy link to clipboard
Copied
Ok, working comp posted. Someone asked about the whole process, so with a hat tip to c.pfaffenbichler I'll go through the workflow.
Part 1, building the UI to be used as a Smart Object for various product angles. Using pngs, exported from Figma, with as many as 20 Locales. The first action calls up the "Load Files into Stack Script". In the Posted PSD, the images brought in are EN, JA, NO, IT. The action continues by building out a group for each, based on the language and putting a vector hiding mask over each group. The action continues by sorting the correct image layer into their named group. Finally the action makes a name based Layer Comp, controlling the visibility of each group. This saves as a UI Build that will go into various assets. In the end this psd has four Layer Comps named EN, JA, NO and IT
Part 2 is to place the UI Build as a Smart Object into the product or lifestyle comp. Once complete an action builds out the same layer Comps EN, JA, NO, and IT. Now both Layer Comps need to be synced/paired, the one inside the Smart Object with the Layer Comp in the working comp. This is the part c.pfaffenbichler resolved. That action pairs and syncs them, doing away with a manual, potentially erroneous, result. Now clicking on the Layer Comp in the worker, drives the change in the smart object with out having to open it.
The last action builds on the "Export Layer Comps to Files" script, with some twists, but in the end I'll have 4 files named EN.psd, JA.psd, NO.psd, and IT.psd
Hope this helps prompt new workflow ideas.
Copy link to clipboard
Copied
Thank you very much for this explanation, this forum is more complete thanks to you!