When a get layerSet id, any way to get all children layers id by ActionManager?

Community Beginner ,
Aug 26, 2022 Aug 26, 2022

Copy link to clipboard

Copied

We can traverse all layers by following code in dfs order:

 

 

/**
 * @Param {LayerSet} layerSet
 */
function traverse(layerSet) {
    const layers = layerSet.layers;
    for (var layer, i = layers.length - 1; i >= 0; i--) {
        layer = layers[i];
        if (layer.typename === 'LayerSet') {
            traverse(layer);
        }
        $.writeln(layer.name);
    }
}

 

But using DOM api is very expensive, I want to use actiom manager api to implements dfs order traverse. For now, I can using following code to traverse all layers in linear order:

 

function traverseByAmInLinearOrder(callback) {
    var ref = new ActionReference();
    ref.putProperty(charIDToTypeID('Prpr'), charIDToTypeID('NmbL'));
    ref.putEnumerated(charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt'));
    var desc = executeActionGet(ref);
    var layerCount = desc.getInteger(charIDToTypeID('NmbL'));
    var i = 0;
    try {
        activeDocument.backgroundLayer;
    } catch (e) {
        i = 1;
    }
    for (i; i <= layerCount; i++) {
        var ref = new ActionReference();
        ref.putIndex(charIDToTypeID('Lyr '), i);
        var desc = executeActionGet(ref);
        var id = desc.getInteger(stringIDToTypeID('layerID'));
        if (desc.getInteger(stringIDToTypeID('layerKind')) !== 13) {
            callback(desc);
        }
    }
}

traverseByAmInLinearOrder(function (desc) {
    $.writeln(desc.getString(stringIDToTypeID('name')));
});

 

In order to traverse layers in dfs order by am, I need to find a method to get all child layers id of layerSet by am. Any bros have ideas?

good good study, day day up!
TOPICS
Actions and scripting , SDK

Views

63

Likes

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

Community Beginner , Sep 06, 2022 Sep 06, 2022

I finally implemet it by following code:

function createLayersTree() {
    var ref = new ActionReference();
    ref.putProperty(charIDToTypeID('Prpr'), charIDToTypeID('NmbL'));
    ref.putEnumerated(charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt'));
    var desc = executeActionGet(ref);
    var layerCount = desc.getInteger(charIDToTypeID('NmbL'));
    var startIndex = app.activeDocument.layers[app.activeDocument.layers.length - 1]
        .isBackgroundLayer
        ? 0
     
...

Likes

Translate

Translate
Community Expert ,
Aug 26, 2022 Aug 26, 2022

Copy link to clipboard

Copied

You are missing the hidden layer, which is the group separator:

 

desc.getInteger(stringIDToTypeID('layerKind')) !== 13

 

it is necessary to solve your problem in this situation: all groups have separators at the beginning and end. You can get information about them by getting the layerSection property for each layer. The start of the group is layerSectionStart, the end of the group is layerSectionEnd. That is, given the layer ID of the group, you can get the layer index and move on until you find the end of the section. Don not forget to take into account nested groups.

You can use this code as a base:

 

var doc = new AM('document'),
    lr = new AM('layer');

var layerSectionContent = getLayersCollection(lr.getProperty(('itemIndex'), lr.getProperty('layerID'))/*<- get active layer ID*/, true)
alert(layerSectionContent.toSource())

function getLayersCollection(idx, getLayerSectionContent) {
    var indexFrom = idx ? (doc.getProperty('hasBackgroundLayer') ? --idx : idx) : doc.getProperty('numberOfLayers'),
        indexTo = doc.getProperty('hasBackgroundLayer') ? 0 : 1;
    return enumLayers(indexFrom, indexTo, getLayerSectionContent);
    function enumLayers(from, to, currentSection, parentItem, group) {
        parentItem = parentItem ? parentItem : [];
        var isDirty = false;
        for (var i = from; i >= to; i--) {
            var layerSection = lr.getProperty('layerSection', i, true).value;
            if (layerSection == 'layerSectionStart') {
                i = enumLayers(i - 1, to, undefined, [], parentItem)
                isDirty = true;
                if (currentSection) return parentItem[0]
                continue;
            }
            if (currentSection && isDirty) return []
            var properties = {};
            //collect properties here
            properties.layerKind = lr.getProperty('name', i, true)
            properties.id = lr.getProperty('layerID', i, true)
            if (layerSection == 'layerSectionEnd') {
                for (o in properties) { parentItem[o] = properties[o] }
                group.push(parentItem);
                return i;
            } else {
                parentItem.push(properties)
                if (currentSection && !isDirty) return parentItem
            }
        }
        return parentItem
    }
}

function AM(target, order) {
    var s2t = stringIDToTypeID,
        t2s = typeIDToStringID;
    target = target ? s2t(target) : null;
    this.getProperty = function (property, id, idxMode) {
        property = s2t(property);
        (r = new ActionReference()).putProperty(s2t('property'), property);
        id != undefined ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id)) :
            r.putEnumerated(target, s2t('ordinal'), order ? s2t(order) : s2t('targetEnum'));
        return getDescValue(executeActionGet(r), property)
    }
    this.hasProperty = function (property, id, idxMode) {
        property = s2t(property);
        (r = new ActionReference()).putProperty(s2t('property'), property);
        id ? (idxMode ? r.putIndex(target, id) : r.putIdentifier(target, id))
            : r.putEnumerated(target, s2t('ordinal'), order ? s2t(order) : s2t('targetEnum'));
        return executeActionGet(r).hasKey(property)
    }
    function getDescValue(d, p) {
        switch (d.getType(p)) {
            case DescValueType.OBJECTTYPE: return { type: t2s(d.getObjectType(p)), value: d.getObjectValue(p) };
            case DescValueType.LISTTYPE: return d.getList(p);
            case DescValueType.REFERENCETYPE: return d.getReference(p);
            case DescValueType.BOOLEANTYPE: return d.getBoolean(p);
            case DescValueType.STRINGTYPE: return d.getString(p);
            case DescValueType.INTEGERTYPE: return d.getInteger(p);
            case DescValueType.LARGEINTEGERTYPE: return d.getLargeInteger(p);
            case DescValueType.DOUBLETYPE: return d.getDouble(p);
            case DescValueType.ALIASTYPE: return d.getPath(p);
            case DescValueType.CLASSTYPE: return d.getClass(p);
            case DescValueType.UNITDOUBLE: return (d.getUnitDoubleValue(p));
            case DescValueType.ENUMERATEDTYPE: return { type: t2s(d.getEnumerationType(p)), value: t2s(d.getEnumerationValue(p)) };
            default: break;
        };
    }
}

 

2022-08-26_13-11-57.png

Likes

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
Community Beginner ,
Sep 06, 2022 Sep 06, 2022

Copy link to clipboard

Copied

hidden layer(layerKind=13) is useless for most case, so I skip it.

good good study, day day up!

Likes

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
Community Beginner ,
Sep 06, 2022 Sep 06, 2022

Copy link to clipboard

Copied

LATEST

I finally implemet it by following code:

function createLayersTree() {
    var ref = new ActionReference();
    ref.putProperty(charIDToTypeID('Prpr'), charIDToTypeID('NmbL'));
    ref.putEnumerated(charIDToTypeID('Dcmn'), charIDToTypeID('Ordn'), charIDToTypeID('Trgt'));
    var desc = executeActionGet(ref);
    var layerCount = desc.getInteger(charIDToTypeID('NmbL'));
    var startIndex = app.activeDocument.layers[app.activeDocument.layers.length - 1]
        .isBackgroundLayer
        ? 0
        : 1;
    const root = { layerId: null, layers: [] };
    var currentIndex = layerCount;
    function recursive(node) {
        var layerSet;
        while (currentIndex >= startIndex) {
            var ref = new ActionReference();
            ref.putIndex(charIDToTypeID('Lyr '), currentIndex);
            currentIndex--;
            var desc = executeActionGet(ref);
            var id = desc.getInteger(stringIDToTypeID('layerID'));
            var layerKind = desc.getInteger(stringIDToTypeID('layerKind'));
            var layerName = desc.getString(s2t('name'));
            var isGroup = layerKind === 7;
            var isGroupEnd = layerKind === 13;
            if (!isGroup && !isGroupEnd) {
                node.layers.push({
                    layerId: id,
                    layers: [],
                    layerName: layerName
                });
            } else if (isGroup) {
                layerSet = {
                    layerId: id,
                    layers: [],
                    layerName: layerName
                };
                node.layers.push(layerSet);
                recursive(layerSet);
            } else {
                return;
            }
        }
    }
    recursive(root);
    return root;
}

$.writeln(JSON.stringify(createLayersTree(), null, 4));

 

Snipaste_2022-09-07_01-03-33.pngSnipaste_2022-09-07_01-04-06.png

good good study, day day up!

Likes

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