Any efficient way to get all actions list?

Is there an efficient way to get full actions list? Preferably with parent (actionSet) name. Currently constructing a list of the 12 default actions (in one set) takes ~2 seconds (using forEach even up to 3 secs)

    const result = []

    const start = new Date().getTime();

    for (let actionSet of photoshop.app.actionTree ?? []) {
        for (let action of actionSet.actions ?? []) {
            const item = {
                title: action.name,
                data: {path: [actionSet.name, action.name]},
                description: actionSet.name,
            }

            result.push(item)
        }
    }

    const end = new Date().getTime();

    console.log("FOR", end - start);

Was thinking maybe some property that we could get with batchPlay?

Sure.

  • use batchplay getter to read action set at index 1
  • if exists then read its number of childern
  • then you can create an array of descriptors and get its content also by index since you know number of items then you know where to stop
  • repeat similar for its childs

Alchemist can help you to generate getter. You might need to replace ID with index.

Alchemist is using this internally. alchemist/GetInfo.ts at master · jardicc/alchemist · GitHub

Not sure if this will help since this file is a mess and I didn’t want to spend too much time with it since later I can replace its parts with DOM. :smiley: But considering performance I have to decide whether to do that.

I appreciate the answer, but I don’t understand :thinking:

In the code I see you already have IDs, but how do you get them?

  • use batchplay getter to read action set at index 1

But how do you get that action set? What would the descriptor be?

Or do you mean I should get action sets from photoshop.app.actionTree and then loop through them to get actions?


replace _id with _index:1

So getting number of action sets is still through DOM with something like photoshop.app.actionTree.length?

I wouldn’t do that… I would try “count” property.

So how do you get count of action sets? Both in Alchemist code and here in screenshots I see descriptors where you already have the sets :confused:

See the second screenshot “count” property of any action set. This tells you the number of sets in total. If you add more then value will increment starting with zero.

OK, this got me so confused - zero based count === 0 means there’s one set and the totally opposite one based index (probably someone at Adobe mixed up the buttons when implementing). Also having sets count on every set… :man_facepalming: Can you delete all sets? What’s the count then? Don’t see how I can restore default set, so not too brave to test it :slight_smile: I guess then you can’t get count at all, because there are no sets :smiley:

Yes you can’t :smiley: …

So my final code now is:

const getActions = () => {
    const result = []

    for (let action of getAppActions() ?? []) {
        const item= {
            title: action.name,
            data: {path: [action.parentName, action.name]},
            description: action.parentName,
        }

        result.push(item)
    }

    return result
}

const getAppActions = () => {
    const setsCount = bp([
        {
            "_obj": "get",
            "_target": [
                {"_ref": "actionSet", "_index": 1},
            ],
            "_options": {"dialogOptions": "dontDisplay"}
        }
    ])[0].count ?? null

    if (setsCount === null) {
        return []
    }

    const setsDescriptors = []

    for (let i = 1; i <= setsCount + 1; i++) {
        setsDescriptors.push(
            {
                "_obj": "get",
                "_target": [
                    {"_ref": "actionSet", "_index": i}
                ],
                "_options": {"dialogOptions": "dontDisplay"}
            }
        )
    }

    const setsData = bp(setsDescriptors)

    if (!setsData.length) {
        return []
    }

    const actionsDescriptors = []

    for (let i = 0; i < setsData.length; i++) {
        let setData = setsData[i]

        if (!setData.numberOfChildren) {
            continue
        }

        for (let j = 1; j <= setData.numberOfChildren; j++) {
            actionsDescriptors.push(
                {
                    "_obj": "get",
                    "_target": [
                        {"_ref": "actionSet", "_index": j},
                        {"_ref": "actionSet", "_index": setData.itemIndex},
                    ],
                    "_options": {"dialogOptions": "dontDisplay"}
                }
            )
        }
    }

    const actionsData = bp(actionsDescriptors)

    return actionsData || []
}

Basically:

  • Get count of sets
  • Get data for these sets
  • Get actions for each set containing children

These 3 BatchPlays and looping to get custom structure takes 20-100 ms in total (instead of previous 2 seconds)

Yes, that is what I meant. :slight_smile: But check what happens if you have exactly one actionSet or none. Just to be sure :slight_smile: I would expect this to fail when there is none.

I think this should take care of it

    const setsCount = bp(descriptors)[0].count ?? null

    if (setsCount === null) {
        return []
    }

I’ll try it later on beta after I backup the default set

@Karmalakas Is your solution still the best thing to do when getting all actions in sets?

Don’t know. Would need to revisit and test if DOM has improved, but I believe BP is still the closest to Ps internals, that we have access to, so it should be faster anyway