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

1 Like

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.

1 Like

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)

2 Likes

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

1 Like