Copy link to clipboard
Copied
Hello, I am here to find a script or action that combines every objects outside of a particular group. It may need a condition that if the group has pixel mask, clipping masks, or layer effects which show outside, then combine all in a new group which has the same name of current group. If the group has no accompanying object, then do nothing.
Here is an example:
result:
I have a script which create new group via current one, but the Photoshop default conditional actions made me confused so I came here.
Thank you everyone.
I apologize, I had forgotten to remove the alerts I had used for testing in the code I posted.
Please try this:
// put all groups with layer mask, vector mask, layer styles, clipping mask in groups of same name;
// 2022, use it at your own risk;
if (app.documents.length > 0) {
var theLayers = collectGroupsNamesIndexAndIdentifier();
for (var x = 0; x < theLayers.length; x++) {
selectLayerByID(theLayers[x][2], false);
groupSelectedLayers (theLayers[x][0])
}
};
////// collect layers /////
...
Copy link to clipboard
Copied
What do you mean by »every objects outside of a particular group« exactly?
Copy link to clipboard
Copied
Sorry for my confusing wording, what I mentioned are pixel masks, clipping masks, or layer effects which shown outside the group
Copy link to clipboard
Copied
The one »problem« I see is that multiple Layers might be clipping masked to one group so that might need some additional checking, but what is giving you problems?
Copy link to clipboard
Copied
I agree with c.pfaffenbichler. You migh try to merge down slowly looking at your photo to be sure you don't block something you need to show. Be sure to save the original. Are you trying to flatten the object?
Copy link to clipboard
Copied
Hello all, so sorry about my late reply. Let me provide more details.
First I have these groups, each has or or some externally rendered object:
- normal: fine group, has nothing to do with
- pattern: has a clipping mask
- txt: has a pixel mask
- base: has layer effect
Any group containing one or more of the above characteristics (pixel mask, clipping masks, or layer effects) would be put into a new group from current one, which has the same name:
Shortened version:
Copy link to clipboard
Copied
You can try this.
// put all groups with layer mask, vector mask, layer styles, clipping mask in groups of same name;
// 2022, use it at your own risk;
if (app.documents.length > 0) {
var theLayers = collectGroupsNamesIndexAndIdentifier();
alert ("\n"+theLayers.join("\n"));
for (var x = 0; x < theLayers.length; x++) {
selectLayerByID(theLayers[x][2], false);
groupSelectedLayers (theLayers[x][0])
}
};
////// collect layers //////
function collectGroupsNamesIndexAndIdentifier () {
// 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 == "layerSectionStart") {
alert (layerDesc.getString(stringIDToTypeID('name')));
var hasMask = layerDesc.getBoolean(stringIDToTypeID('hasUserMask'));
var hasVectorMask = layerDesc.getBoolean(stringIDToTypeID('hasVectorMask'));
var hasLayerStyle = layerDesc.hasKey(stringIDToTypeID('layerEffects'));
try {var ref2 = new ActionReference();
ref2.putIndex( charIDToTypeID( "Lyr " ), m+1);
var layerDesc2 = executeActionGet(ref2);
var isClippingGrouped = layerDesc2.getBoolean(stringIDToTypeID('group'))}
catch (e) {isClippingGrouped = false};
// collect if condition is met;
if (hasMask == true || hasVectorMask == true || hasLayerStyle == true || isClippingGrouped == true) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
theLayers.push([theName, theIndex, theID])
}
};
}
catch (e) {};
};
return theLayers
};
////// based on code by mike hale, via paul riggott //////
function selectLayerByID(id,add){
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);
}
};
////// group //////
function groupSelectedLayers (theName) {
var desc159 = new ActionDescriptor();
var ref114 = new ActionReference();
var idlayer = stringIDToTypeID( "layer" );
var idordinal = stringIDToTypeID( "ordinal" );
var idtargetEnum = stringIDToTypeID( "targetEnum" );
var idnull = stringIDToTypeID( "null" );
var idname = stringIDToTypeID( "name" );
ref114.putEnumerated(idlayer, idordinal, idtargetEnum);
desc159.putReference(idnull, ref114 );
desc159.putString(idname, "aaa" );
executeAction( stringIDToTypeID( "groupLayersEvent" ), desc159, DialogModes.NO );
var desc63 = new ActionDescriptor();
var ref37 = new ActionReference();
ref37.putEnumerated( idlayer, idordinal, idtargetEnum );
desc63.putReference( idnull, ref37 );
var desc64 = new ActionDescriptor();
desc64.putString(idname, theName);
desc63.putObject(stringIDToTypeID( "to" ), idlayer, desc64);
executeAction(stringIDToTypeID( "set" ), desc63, DialogModes.NO)
};
Copy link to clipboard
Copied
Thank you so much! I tried the script, it worked well. But had some popup while playing and also, maybe it worked with the contained groups, so it's really annoying to turn off these notifications:
This script works for me, but can you improve this? Many thanks!
Copy link to clipboard
Copied
I don’t get alerts on my test-file, could you provide a file for which you get such alerts?
Copy link to clipboard
Copied
In fact, the script works like all my other files, so I created a test one:
https://drive.google.com/file/d/1jIugzLMrMdyn6sE07R6roIVOilWK5NF-/view?usp=share_link
And this is a video when I run the script:
https://drive.google.com/file/d/10lR-EW6MCTMslNV2MH6x2bmBfrMOFBcS/view?usp=share_link
Copy link to clipboard
Copied
I apologize, I had forgotten to remove the alerts I had used for testing in the code I posted.
Please try this:
// put all groups with layer mask, vector mask, layer styles, clipping mask in groups of same name;
// 2022, use it at your own risk;
if (app.documents.length > 0) {
var theLayers = collectGroupsNamesIndexAndIdentifier();
for (var x = 0; x < theLayers.length; x++) {
selectLayerByID(theLayers[x][2], false);
groupSelectedLayers (theLayers[x][0])
}
};
////// collect layers //////
function collectGroupsNamesIndexAndIdentifier () {
// 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 == "layerSectionStart") {
var hasMask = layerDesc.getBoolean(stringIDToTypeID('hasUserMask'));
var hasVectorMask = layerDesc.getBoolean(stringIDToTypeID('hasVectorMask'));
var hasLayerStyle = layerDesc.hasKey(stringIDToTypeID('layerEffects'));
try {var ref2 = new ActionReference();
ref2.putIndex( charIDToTypeID( "Lyr " ), m+1);
var layerDesc2 = executeActionGet(ref2);
var isClippingGrouped = layerDesc2.getBoolean(stringIDToTypeID('group'))}
catch (e) {isClippingGrouped = false};
// collect if condition is met;
if (hasMask == true || hasVectorMask == true || hasLayerStyle == true || isClippingGrouped == true) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
var theIndex = layerDesc.getInteger(stringIDToTypeID('itemIndex'));
theLayers.push([theName, theIndex, theID])
}
};
}
catch (e) {};
};
return theLayers
};
////// based on code by mike hale, via paul riggott //////
function selectLayerByID(id,add){
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);
}
};
////// group //////
function groupSelectedLayers (theName) {
var desc159 = new ActionDescriptor();
var ref114 = new ActionReference();
var idlayer = stringIDToTypeID( "layer" );
var idordinal = stringIDToTypeID( "ordinal" );
var idtargetEnum = stringIDToTypeID( "targetEnum" );
var idnull = stringIDToTypeID( "null" );
var idname = stringIDToTypeID( "name" );
ref114.putEnumerated(idlayer, idordinal, idtargetEnum);
desc159.putReference(idnull, ref114 );
desc159.putString(idname, "aaa" );
executeAction( stringIDToTypeID( "groupLayersEvent" ), desc159, DialogModes.NO );
var desc63 = new ActionDescriptor();
var ref37 = new ActionReference();
ref37.putEnumerated( idlayer, idordinal, idtargetEnum );
desc63.putReference( idnull, ref37 );
var desc64 = new ActionDescriptor();
desc64.putString(idname, theName);
desc63.putObject(stringIDToTypeID( "to" ), idlayer, desc64);
executeAction(stringIDToTypeID( "set" ), desc63, DialogModes.NO)
};
Copy link to clipboard
Copied
This help me a lot! Thank you for your help, million thanks!