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

Photoshop Scripting: linkedLayers property on layers does not seem to work.

Participant ,
Oct 27, 2021 Oct 27, 2021

Copy link to clipboard

Copied

I'm trying to detect if an artlayer has layers or adjustment layers linked to it.

There is the property linkedlayers that should be an array of linkers linked to this layer.

I tried this simple code on many linked layers, but the array.length is always 0.

I don't see what's wrong here...

 

var layer = app.activeDocument.activeLayer;

alert(layer.linkedLayers.length);

 

I'm using PS2020...

What I consider a linked layer for example an artlayer, with an curve adjustmentlayer linked on it. I would expect when the active layer is the artlayer, there is one linkedlayer in the array, the curve adjustment layer... or am I missing something?

TOPICS
Actions and scripting

Views

517

Translate

Translate

Report

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 1 Correct answer

LEGEND , Oct 31, 2021 Oct 31, 2021

 

aL = activeDocument.activeLayer
grpd = [], lrs = [].slice.call(aL.parent.layers)
while(lrs.length) (((pop = lrs.pop()).itemIndex <= aL.itemIndex)
|| (pop.grouped && grpd.push(pop))) || lrs.length = 0; alert(grpd)

 

Now it pushes grouped  layers (to selected layer) to the array, alerted at end.

 

slice.call clones layers to new array. In this case it lets use while instead of for...in statement, while pop() cuts out last item from cloned array (leaving original one not affected)

Votes

Translate

Translate
Adobe
LEGEND ,
Oct 27, 2021 Oct 27, 2021

Copy link to clipboard

Copied

You can't check in artLayer properties if there's any adjustement layer over it.

 

Ps. linkedLayers is to check an array of layer(Set)s connected by 'chain' thing.

Votes

Translate

Translate

Report

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 ,
Oct 27, 2021 Oct 27, 2021

Copy link to clipboard

Copied

Oh! Now I understand, it's for the chain thing! I mean the other linking method.

In action manager code I managed to "link/unlink" a curve to an ArtLayer.

Is there some action manager code to check if a layer is linked or not, and if posible. to what layer?

I Think I can use the index property of a layer to check the layer above it if it's linked, and asume it must be linked to the one below it. But at the very leasy, I need to know if a layer is linked or not.

Maybe I can do a try to unlink every layer and link it again, and when error it was not linked.. but that not a clean or fast way to detect a linked layer I gues.

Votes

Translate

Translate

Report

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
LEGEND ,
Oct 27, 2021 Oct 27, 2021

Copy link to clipboard

Copied

 

lLs = [].slice.call((aL = activeDocument.activeLayer).linkedLayers)
knd = 'LayerKind.CURVES', itmIndx = aL.itemIndex; while(lLs.length)
 (shft=lLs.shift()).kind==knd&&shft.itemIndex>itmIndx&&alert(shft.id)

 

Votes

Translate

Translate

Report

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 ,
Oct 27, 2021 Oct 27, 2021

Copy link to clipboard

Copied

Thanks for your great scripting work, but if I read correctly, This will alert the id if any layer above it if it's a curve? Dut your searching in the linkedLayers array, wich is not the type of linked layer I want to search for.

I mean the linking you do when you want a curve only applied on one layer, you link it using the ALT key and click in between the two layers. I gues thats also called linking, but not what I need.

 

At the end of the day, I want to check a specific artlayer, delete all the linked adjustments/layers that it has.

I'm already doing the same with the layer effects, check if it has layer effects with action manager code, and if so, remove all layer effects.

Votes

Translate

Translate

Report

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
LEGEND ,
Oct 27, 2021 Oct 27, 2021

Copy link to clipboard

Copied

For visible layers:

 

sTT = stringIDToTypeID;
(ref = new ActionReference()).putEnumerated
(sTT('layer'), sTT('ordinal'), sTT('forwardEnum'));
(dsc = new ActionDescriptor()).putReference(sTT('null'), ref)
dsc.putBoolean(sTT('makeVisible'), false);
executeAction(sTT('select'), dsc);
(aL = activeDocument.activeLayer)
.grouped && aL.grouped ^= 1

 

Votes

Translate

Translate

Report

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 ,
Oct 28, 2021 Oct 28, 2021

Copy link to clipboard

Copied

Thanks for your help! It's the .grouped property I was looking for.

 

I made a script to input a layer object, and outputs an array of the layers that are grouped to this layer.

With this array of layers, I can for example delte all layers that were grouped to this layer.

Only downside is that it's selecting the layers to get the layer object to check the grouped property.

Is there a way to get the layer object by index without selecting it?

 

sTT = stringIDToTypeID;

function groupedLayersOfLayer(layer){

	var groupedLayers = [];

	for (var i = layer.itemIndex; i > 0; i --){
        
		var d1 = new ActionDescriptor();
		var r1 = new ActionReference();
		r1.putIndex( sTT('layer'), i );
		d1.putReference( sTT('null'), r1 );
		executeAction( sTT('select'), d1, DialogModes.NO );

		var activeLayer = activeDocument.activeLayer;

		if (activeLayer.grouped === true){
			groupedLayers.push(activeLayer);
		} else {
			break;
		}
	}

    return groupedLayers
}

 

Votes

Translate

Translate

Report

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
LEGEND ,
Oct 28, 2021 Oct 28, 2021

Copy link to clipboard

Copied

Do it a little other way, by selecting the artLayer, the layers over might be grouped with...

 

lrs = [].slice.call((aL = activeDocument.activeLayer).parent.layers)
while(lrs.length) (((pop = lrs.pop()).itemIndex <= aL.itemIndex)
|| (pop.grouped && pop.grouped = 0)) || lrs.length = 0

 

Votes

Translate

Translate

Report

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 ,
Oct 31, 2021 Oct 31, 2021

Copy link to clipboard

Copied

I'm not completly understanding what you mean. The code is also a bit hard to read for me.

I basically already have a layer object, without it being selected. And would like to receive an array of the layers that are grouped with the layer object I input to the function, without selecting all layers above the layer to test if it's grouped or not. If it's imposible wihout selecting any layer, I stick to the function I already have working, as seen above. If it's posible, could you edit my code to make it more readable? Many thanks, your a great PS coder.

 

Votes

Translate

Translate

Report

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
LEGEND ,
Oct 31, 2021 Oct 31, 2021

Copy link to clipboard

Copied

The last code from me does not select any layers to check if they are grouped with other layer.

 

The only what you have to do before you run script is to have a selected layer, the one from which the other ones (over it) will be as the result ungrouped. Try it with my code first.

Votes

Translate

Translate

Report

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 ,
Oct 31, 2021 Oct 31, 2021

Copy link to clipboard

Copied

I tested it, it does what you say it does. The layer object needs to be selected, but the grouped layers don't, whats at least better than my function. But I don't want the grouped layers to be ungrouped, I want an array of those grouped layers. Sometimes I just need to delete the grouped layers, other times, I just want to know if there are grouped layers. For my own learning process, I would like to know what your script actually does.. The slice.call, .pop().. it looks fuzzy to me, it's efficient for sure, but for the avarage javascripter a bit hard to read.

Votes

Translate

Translate

Report

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
LEGEND ,
Oct 31, 2021 Oct 31, 2021

Copy link to clipboard

Copied

 

aL = activeDocument.activeLayer
grpd = [], lrs = [].slice.call(aL.parent.layers)
while(lrs.length) (((pop = lrs.pop()).itemIndex <= aL.itemIndex)
|| (pop.grouped && grpd.push(pop))) || lrs.length = 0; alert(grpd)

 

Now it pushes grouped  layers (to selected layer) to the array, alerted at end.

 

slice.call clones layers to new array. In this case it lets use while instead of for...in statement, while pop() cuts out last item from cloned array (leaving original one not affected)

Votes

Translate

Translate

Report

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 ,
Nov 03, 2021 Nov 03, 2021

Copy link to clipboard

Copied

Your code worked! Now that I have two functions working (seamingly reliable) and performance tested both, I see big differences in speed depending on the situation.

Your code is really slow when it comes to checking layers in big psd's, and placed low in the layer stack.

Sometimes it can take up to 6 seconds to check the layer's grouped layers, where "my"method can be much quicker, but in some situations yours can be a bit faster. But spikes of 6 seconds are just too much.

 

I made a code to test the performance, just click on a layer, and run the code, and it will alert the time it took both to complete...

sTT = stringIDToTypeID;
function layersGroupedLayers01(layer){

    var ref = new ActionReference(); 
        
    ref.putProperty( charIDToTypeID("Prpr"), charIDToTypeID( "Bckg" )); 
    ref.putEnumerated(charIDToTypeID( "Lyr " ),charIDToTypeID( "Ordn" ),charIDToTypeID( "Back" ));
        
    var desc =  executeActionGet(ref); 
    var backgroundLayerPresent = desc.getBoolean(charIDToTypeID( "Bckg" )); 
    
    var groupedLayers = new Array();
    var itemIndex = layer.itemIndex

    if (backgroundLayerPresent === true){
        itemIndex = itemIndex - 1;
        }
    
    for (var i = itemIndex + 1; ; i ++){

        try {
		var d1 = new ActionDescriptor();
		var r1 = new ActionReference();
		r1.putIndex( sTT('layer'), i );
		d1.putReference( sTT('null'), r1 );
		executeAction( sTT('select'), d1, DialogModes.NO );
        } catch (e) {
            alert(e)
            break;
            }

        var activeLayer = activeDocument.activeLayer;
        if (activeLayer.grouped === true){
            groupedLayers.push(activeLayer);
            } else {
                break;
                }
            }

    return groupedLayers
    }
function layersGroupedLayers02(layer){

    aL = layer
    grpd = [], lrs = [].slice.call(aL.parent.layers)
    
    while(lrs.length) (((pop = lrs.pop()).itemIndex <= aL.itemIndex)
    || (pop.grouped && grpd.push(pop))) || lrs.length = 0;

    return grpd
    }
var layer = activeDocument.activeLayer
var date01 = new Date;
var date01 = date01.getTime()
layersGroupedLayers01(layer)
var date02 = new Date;
var date02 = date02.getTime()
layersGroupedLayers02(layer)
var date03 = new Date;
var date03 = date03.getTime()

alert("Function01: " + (date02 - date01) + "\nFunction02: " +  (date03 - date02))

 

Is there a way to improve your codes performance? I like your method to not select other layers, and maybe also more reliable, but the performance...

Votes

Translate

Translate

Report

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
LEGEND ,
Nov 04, 2021 Nov 04, 2021

Copy link to clipboard

Copied

Maybe try with Action Manager to check if a layer is grouped:

 

sTT = stringIDToTypeID; function grouped(v) {
	(ref = new ActionReference()).putIndex(sTT('layer'), v)
	return executeActionGet(ref).getBoolean(sTT('group'))
}

aL = (aD = activeDocument).activeLayer
grpd = [], lrs = [].slice.call(aL.parent.layers)
bGL = aD.artLayers[aD.artLayers.length - 1].isBackgroundLayer
while(lrs.length) (((iI = (pop = lrs.pop()).itemIndex)<=aL.itemIndex)
||(grouped(iI-bGL) && grpd.push(pop))) || lrs.length = 0;alert(grpd)

 

Votes

Translate

Translate

Report

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 ,
Nov 11, 2021 Nov 11, 2021

Copy link to clipboard

Copied

Thx! I now have three scripts to collect the grouped layers to the active layer.

The last method does seem to be a bit slower, but at least I have 3 working functions now!

 

 

And your correct, when I use your Action Manager code in my function to check if it's grouped, I do get a nice performance boost!

Votes

Translate

Translate

Report

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
LEGEND ,
Nov 11, 2021 Nov 11, 2021

Copy link to clipboard

Copied

LATEST

Loll, if you think so why then you marked as correct solution the slower DOM method 😉

Votes

Translate

Translate

Report

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