Copy link to clipboard
Copied
Hi!
I am having a hard time trying to load the selection of all the layer masks inside a group. The group can contain different numbers of layers that contain layer masks (names of the layers will be different, but the group name is always the same) . I would like to have a selection of all layer masks, like clicking on the mask with cmd+shift.
I don’t quite understand how loops work, and I am struggling to make it work.
// load layer masks of layers in group of certain name;
// 2024, use it at your own risk;
if (app.documents.length > 0) {
var theLayers = collectLayersInGroupOfName ("group name");
for (var m = 0; m < theLayers.length; m++) {
loadLayerMaskById(theLayers[m][2])
};
};
////// collect layers in group of name //////
function collectLayersInGroupOfName (theRegExp) {
var theGroup = collectLayersOfName (theRegExp, true);
if (theGroup.length == 1) {
// get number of layers;
var ref
...
Sorry, must have forgotten that; just delete the line
alert (theGroup.join("\n"));
altogether.
Copy link to clipboard
Copied
What is the problem exactly?
Please provide a sample file.
Copy link to clipboard
Copied
Copy link to clipboard
Copied
// load layer masks of layers in group of certain name;
// 2024, use it at your own risk;
if (app.documents.length > 0) {
var theLayers = collectLayersInGroupOfName ("group name");
for (var m = 0; m < theLayers.length; m++) {
loadLayerMaskById(theLayers[m][2])
};
};
////// collect layers in group of name //////
function collectLayersInGroupOfName (theRegExp) {
var theGroup = collectLayersOfName (theRegExp, true);
if (theGroup.length == 1) {
// 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);
//checkDesc2 (layerDesc, true);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// if group collect values;
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart" && isBackground != true) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
var theParentId = layerDesc.getInteger(stringIDToTypeID('parentLayerID'));
//var theBounds = layerDesc.getObjectValue(stringIDToTypeID("bounds"));
//var theseBounds = [theBounlayerDescds.getUnitDoubleValue(stringIDToTypeID("left")), theBounds.getUnitDoubleValue(stringIDToTypeID("top")), theBounds.getUnitDoubleValue(stringIDToTypeID("right")), theBounds.getUnitDoubleValue(stringIDToTypeID("bottom"))];
var theCheck = false;
while (theParentId != -1) {
if (Number(theParentId) == Number(theGroup[0][2])) {theCheck = true};
var theParent = getLayerNameAndParentIdById (theParentId);
theParentId = theParent[3];
};
if (theCheck == true) {theLayers.push([theName, theIndex, theID])}
};
}
catch (e) {};
};
return theLayers
} else {alert ("no such group")}
};
////// based on code by mike hale, via paul riggott //////
function selectLayerByID(id,add){
try {
add = undefined ? add = false:add
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID("Lyr "), id);
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);
}
} catch (e) {}
};
////// has layer mask //////
function hasLayerMask () {
var m_Dsc01, m_Ref01;
m_Ref01 = new ActionReference();
m_Ref01.putEnumerated(stringIDToTypeID("layer"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
m_Dsc01 = executeActionGet(m_Ref01);
return m_Dsc01.hasKey(charIDToTypeID("Usrs"));
};
////// load layer mask //////
function loadSelectionOfLayerMask() {
try {
var idchannel = stringIDToTypeID( "channel" );
var desc70 = new ActionDescriptor();
var ref9 = new ActionReference();
ref9.putProperty( idchannel, stringIDToTypeID( "selection" ) );
desc70.putReference( stringIDToTypeID( "null" ), ref9 );
var ref10 = new ActionReference();
ref10.putEnumerated( idchannel, idchannel, stringIDToTypeID( "mask" ) );
desc70.putReference( stringIDToTypeID( "to" ), ref10 );
executeAction( stringIDToTypeID( "set" ), desc70, DialogModes.NO );
} catch (_error) {alert (_error)}
};
////// collect layers //////
function collectLayersOfName (theRegExp, isGroup) {
// 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"));
// if group collect values;
if (layerSet != "layerSectionEnd" /*&& layerSet != "layerSectionStart" && isBackground != true*/) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
var theColor = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("color")));
if (layerSet == "layerSectionStart" && isGroup == true) {
if (theName.match(theRegExp) != null) {theLayers.push([theName, theIndex, theID, theColor])}
};
if (layerSet != "layerSectionStart" && isGroup == false) {
if (theName.match(theRegExp) != null) {theLayers.push([theName, theIndex, theID, theColor])}
};
};
}
catch (e) {};
};
return theLayers
};
////// get parentid //////
function getLayerNameAndParentIdById (theID) {
var ref = new ActionReference();
ref.putIdentifier( charIDToTypeID( "Lyr " ), theID);
var layerDesc = executeActionGet(ref);
var theName = layerDesc.getString(stringIDToTypeID('name'));
//var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
var theParentId = layerDesc.getInteger(stringIDToTypeID('parentLayerID'));
return [theName, theIndex, theID, theParentId]
};
////// load layer mask //////
function loadLayerMaskById (theID) {
try {
selectLayerByID(theID, false);
var idchannel = stringIDToTypeID( "channel" );
if (hasSelection() == false) {
var desc5 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putProperty( idchannel, stringIDToTypeID( "selection" ) );
desc5.putReference( stringIDToTypeID( "null" ), ref1 );
var ref2 = new ActionReference();
ref2.putEnumerated( idchannel, idchannel, stringIDToTypeID( "mask" ) );
ref2.putIdentifier( stringIDToTypeID( "layer" ), theID );
desc5.putReference( stringIDToTypeID( "to" ), ref2 );
executeAction( stringIDToTypeID( "set" ), desc5, DialogModes.NO );
} else {
var desc7 = new ActionDescriptor();
var ref3 = new ActionReference();
ref3.putEnumerated( idchannel, idchannel, stringIDToTypeID( "mask" ) );
ref3.putIdentifier( stringIDToTypeID( "layer" ), theID );
desc7.putReference( stringIDToTypeID( "null" ), ref3 );
var ref4 = new ActionReference();
ref4.putProperty( idchannel, stringIDToTypeID( "selection" ) );
desc7.putReference( stringIDToTypeID( "to" ), ref4 );
executeAction( stringIDToTypeID( "add" ), desc7, DialogModes.NO );
}
} catch (e) {}
};
////// check for selection //////
function hasSelection(){
var ref10 = new ActionReference();
ref10.putProperty(stringIDToTypeID("property"), stringIDToTypeID("selection"));
ref10.putEnumerated( charIDToTypeID( "Dcmn" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
var docDesc = executeActionGet(ref10);
return docDesc.hasKey(stringIDToTypeID("selection"));
};
Copy link to clipboard
Copied
Thanks! That works 🙂 It works with the file I attached, but what if there is another group (with a different name)? I get an error "no such group". Is there a workaround?
Thanks again!
Copy link to clipboard
Copied
You specifically stated »names of the layers will be different, but the group name is always the same«.
You can either insert the correct name instead of »group name« in the line
var theLayers = collectLayersInGroupOfName ("group name");
or adapt the Script to take other input (the selected layer’s/group’s name, text input, …).
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Seems to work fine here:
Copy link to clipboard
Copied
Like I stated it works here, attached a recording:
Copy link to clipboard
Copied
Is it possible that you have two or more Groups of the same name?
Edit: I specifically included
var theGroup = collectLayersOfName (theRegExp, true);
if (theGroup.length == 1) {
in the layer-collecting function to make sure there is exactly one group of the specified name.
Copy link to clipboard
Copied
Copy link to clipboard
Copied
That’s why it matters to provide meaningful test files.
You can change the code to use a String instead of a RegExp and then change the check from »match« to »==«.
Copy link to clipboard
Copied
I am sorry, we have different types of file and I didn't realize that what is inside "" could affect the rest.
I will give it a try. Thanks for all the time invested on this 🙂
Copy link to clipboard
Copied
Have you been able to adapt the Script successfully?
Copy link to clipboard
Copied
No, I was messing around with it yesterday but RegExp are out of my poor script level and I don't quite understand it well. Thanks again.
Copy link to clipboard
Copied
Actually it should be a String now.
Please try
// load layer masks of layers in group of certain name;
// 2024, use it at your own risk;
if (app.documents.length > 0) {
var theLayers = collectLayersInGroupOfName ("[group name]");
for (var m = 0; m < theLayers.length; m++) {
loadLayerMaskById(theLayers[m][2])
};
};
////// collect layers in group of name //////
function collectLayersInGroupOfName (theRegExp) {
var theGroup = collectLayersOfName (String(theRegExp), true);
if (theGroup.length == 1) {
// 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);
//checkDesc2 (layerDesc, true);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// if group collect values;
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart" && isBackground != true) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
var theParentId = layerDesc.getInteger(stringIDToTypeID('parentLayerID'));
//var theBounds = layerDesc.getObjectValue(stringIDToTypeID("bounds"));
//var theseBounds = [theBounlayerDescds.getUnitDoubleValue(stringIDToTypeID("left")), theBounds.getUnitDoubleValue(stringIDToTypeID("top")), theBounds.getUnitDoubleValue(stringIDToTypeID("right")), theBounds.getUnitDoubleValue(stringIDToTypeID("bottom"))];
var theCheck = false;
while (theParentId != -1) {
if (Number(theParentId) == Number(theGroup[0][2])) {theCheck = true};
var theParent = getLayerNameAndParentIdById (theParentId);
theParentId = theParent[3];
};
if (theCheck == true) {theLayers.push([theName, theIndex, theID])}
};
}
catch (e) {};
};
return theLayers
} else {alert ("no such group")}
};
////// based on code by mike hale, via paul riggott //////
function selectLayerByID(id,add){
try {
add = undefined ? add = false:add
var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID("Lyr "), id);
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);
}
} catch (e) {}
};
////// has layer mask //////
function hasLayerMask () {
var m_Dsc01, m_Ref01;
m_Ref01 = new ActionReference();
m_Ref01.putEnumerated(stringIDToTypeID("layer"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
m_Dsc01 = executeActionGet(m_Ref01);
return m_Dsc01.hasKey(charIDToTypeID("Usrs"));
};
////// load layer mask //////
function loadSelectionOfLayerMask() {
try {
var idchannel = stringIDToTypeID( "channel" );
var desc70 = new ActionDescriptor();
var ref9 = new ActionReference();
ref9.putProperty( idchannel, stringIDToTypeID( "selection" ) );
desc70.putReference( stringIDToTypeID( "null" ), ref9 );
var ref10 = new ActionReference();
ref10.putEnumerated( idchannel, idchannel, stringIDToTypeID( "mask" ) );
desc70.putReference( stringIDToTypeID( "to" ), ref10 );
executeAction( stringIDToTypeID( "set" ), desc70, DialogModes.NO );
} catch (_error) {alert (_error)}
};
////// collect layers //////
function collectLayersOfName (theString, isGroup) {
// 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"));
// if group collect values;
if (layerSet != "layerSectionEnd" /*&& layerSet != "layerSectionStart" && isBackground != true*/) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
var theColor = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("color")));
if (layerSet == "layerSectionStart" && isGroup == true) {
if (theName == theString) {theLayers.push([theName, theIndex, theID, theColor])}
};
if (layerSet != "layerSectionStart" && isGroup == false) {
if (theName == theString) {theLayers.push([theName, theIndex, theID, theColor])}
};
};
}
catch (e) {};
};
return theLayers
};
////// get parentid //////
function getLayerNameAndParentIdById (theID) {
var ref = new ActionReference();
ref.putIdentifier( charIDToTypeID( "Lyr " ), theID);
var layerDesc = executeActionGet(ref);
var theName = layerDesc.getString(stringIDToTypeID('name'));
//var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
var theParentId = layerDesc.getInteger(stringIDToTypeID('parentLayerID'));
return [theName, theIndex, theID, theParentId]
};
////// load layer mask //////
function loadLayerMaskById (theID) {
try {
selectLayerByID(theID, false);
var idchannel = stringIDToTypeID( "channel" );
if (hasSelection() == false) {
var desc5 = new ActionDescriptor();
var ref1 = new ActionReference();
ref1.putProperty( idchannel, stringIDToTypeID( "selection" ) );
desc5.putReference( stringIDToTypeID( "null" ), ref1 );
var ref2 = new ActionReference();
ref2.putEnumerated( idchannel, idchannel, stringIDToTypeID( "mask" ) );
ref2.putIdentifier( stringIDToTypeID( "layer" ), theID );
desc5.putReference( stringIDToTypeID( "to" ), ref2 );
executeAction( stringIDToTypeID( "set" ), desc5, DialogModes.NO );
} else {
var desc7 = new ActionDescriptor();
var ref3 = new ActionReference();
ref3.putEnumerated( idchannel, idchannel, stringIDToTypeID( "mask" ) );
ref3.putIdentifier( stringIDToTypeID( "layer" ), theID );
desc7.putReference( stringIDToTypeID( "null" ), ref3 );
var ref4 = new ActionReference();
ref4.putProperty( idchannel, stringIDToTypeID( "selection" ) );
desc7.putReference( stringIDToTypeID( "to" ), ref4 );
executeAction( stringIDToTypeID( "add" ), desc7, DialogModes.NO );
}
} catch (e) {}
};
////// check for selection //////
function hasSelection(){
var ref10 = new ActionReference();
ref10.putProperty(stringIDToTypeID("property"), stringIDToTypeID("selection"));
ref10.putEnumerated( charIDToTypeID( "Dcmn" ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
var docDesc = executeActionGet(ref10);
return docDesc.hasKey(stringIDToTypeID("selection"));
};
edited
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Sorry, must have forgotten that; just delete the line
alert (theGroup.join("\n"));
altogether.
Copy link to clipboard
Copied
That is great! All solved now 🙂
Copy link to clipboard
Copied
I'm always in awe when I see such scripts, I guess that you work with snippets, and assemble them together, or do you mostly code everything?
Copy link to clipboard
Copied
I'm always in awe when I see such scripts, I guess that you work with snippets, and assemble them together, or do you mostly code everything?
I try to re-use existing functions (and adapt them if necessary) but I lack the discipline to work with a proper library.
Copy link to clipboard
Copied
Why do you need this selection? In general, it is useless
Copy link to clipboard
Copied
We have some layers of effects that we only want to affect the visible part of the layers inside the group. We can clip them to the group, but to reduce the file size, we delete the parts of the image that are not in use (the black parts of the mask).
It probably doesn't make sense to you, but it is useful to us.