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

Script Needed - Convert to Color Fill

Explorer ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

I'm bouncing from Photoshop to CSP and back to liquefy multiple layers at once since Photoshop can't do that. Certain layer features are lost in the conversion, one being color-fill layers. CSP converts them to a normal layer with any region revealed by the mask filled with a flat color.

I would like a script where I can click on that layer, and it will convert it back into a Color Fill Layer and delete the one CSP made. Can someone help me out? Thanks in advance.

(see attached image)

TOPICS
Actions and scripting

Views

326

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 Expert , Jan 07, 2024 Jan 07, 2024

@Tyler229371107i00 

 

The following script will apply the last used liquify mesh to all layers and layer masks in a single pass!

 

/*
Liquify Selected Layers & Masks using Last Mesh.jsx
v1.0, 8th January 2024, Stephen Marsh
*/

#target photoshop

function main() {

    // Save the current dialog display settings
    var savedDisplayDialogs = app.displayDialogs;
    app.displayDialogs = DialogModes.NO;

    // Capture the initial layer visibility and layer selection
    var currentLayersState = g
...

Votes

Translate

Translate
Adobe
Explorer ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

Alternatively, if someone can write a script to take a liquified edit and apply it to a selection of multiple layers, that would be an even better solution so I don't have to use CSP. Still, I've contacted a scripter before, and they said Adobe doesn't let you do that. I'm an artist, so I have no idea if that is true.

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
Community Expert ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

You can use the last liquify mesh settings... Or save and load mesh settings from a .msh file. If working in the same session you can just reapply the previous Liquify to new layers which will automatically use the last mesh.

 

last-liquify.png

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
Explorer ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

I should have assumed this would be suggested. This is too slow when dealing with hundreds of layers.

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
Community Expert ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

quote

I should have assumed this would be suggested. This is too slow when dealing with hundreds of layers.


By @Tyler229371107i00

 

EDIT:

 

Here is the script. Run the liquify filter as required on the first layer.

 

Then select all other required layers and run the script to apply the last used mesh setting.

 

Note: There is no special check to gracefully ensure that the selected layer kind is suitable/capable of being liquified.

 

 

/*
Liquify Selected Layers using Last Mesh.jsx
v1.0, 8th January 2024, Stephen Marsh
*/

#target photoshop

function main() {

    // Save the current dialog display settings
    var savedDisplayDialogs = app.displayDialogs;
    app.displayDialogs = DialogModes.NO;

    // Capture the initial layer visibility and layer selection
    var currentLayersState = getLayersVisiblity();

    // Get the selected layers: courtesy of jazz-y
    var s2t = stringIDToTypeID;
    (r = new ActionReference()).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
    r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
    var lrs = executeActionGet(r).getList(p),
        sel = new ActionReference();

    // Loop over the selected layers: courtesy of jazz-y
    for (var i = 0; i < lrs.count; i++) {
        sel.putIdentifier(s2t('layer'), p = lrs.getReference(i).getIdentifier(s2t('layerID')));
        (r = new ActionReference()).putIdentifier(s2t('layer'), p);
        (d = new ActionDescriptor()).putReference(s2t("target"), r);
        executeAction(s2t('select'), d, DialogModes.NO);

        // Apply the last liquify filter mesh
        var idLqFy = charIDToTypeID( "LqFy" );
        var desc213 = new ActionDescriptor();
        var idLqMD = charIDToTypeID( "LqMD" );
        desc213.putString( idLqMD, app.preferencesFolder.fsName + "/" + "Liquify Last Mesh.psp" );
        executeAction( idLqFy, desc213, DialogModes.NO );
    }
    // Finish the loop

    // Restore the initial layer visibility and selection
    setLayersVisiblity(currentLayersState);

    // Restore the dialogs
    app.displayDialogs = savedDisplayDialogs;

    app.beep();
    alert("Script completed!");
}

// Single history stage undo
activeDocument.suspendHistory("Liquify Selected Layers using Last Mesh.jsx", "main()");


///// FUNCTIONS /////

function getLayersVisiblity() {
    // by jazz-y
    var s2t = stringIDToTypeID,
        t2s = typeIDToStringID;
    (r = new ActionReference()).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
    r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
    var targetLayers = executeActionGet(r).getList(p),
        seletion = [],
        visiblity = {};
    for (var i = 0; i < targetLayers.count; i++) seletion.push(targetLayers.getReference(i).getIdentifier());
    (r = new ActionReference()).putProperty(s2t('property'), p = s2t('numberOfLayers'));
    r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
    var len = executeActionGet(r).getInteger(p);
    for (var i = 1; i <= len; i++) {
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerSection'));
        r.putIndex(s2t('layer'), i);
        if (t2s(executeActionGet(r).getEnumerationValue(p)) == 'layerSectionEnd') continue;
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerID'));
        r.putIndex(s2t('layer'), i);
        var id = executeActionGet(r).getInteger(p);
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('visible'));
        r.putIndex(s2t('layer'), i);
        var visible = executeActionGet(r).getBoolean(p);
        visiblity[id] = visible;
    }
    return {
        selection: seletion,
        visiblity: visiblity
    };
}

function setLayersVisiblity(layersStateObject) {
    // by jazz-y
    var s2t = stringIDToTypeID;
    for (var a in layersStateObject.visiblity) {
        makeVisible = layersStateObject.visiblity[a] ? "show" : "hide";
        (r = new ActionReference()).putIdentifier(s2t('layer'), a);
        (d = new ActionDescriptor()).putReference(s2t('target'), r);
        executeAction(s2t(makeVisible), d, DialogModes.NO);
    }
    if (layersStateObject.selection.length) {
        var r = new ActionReference();
        for (var i = 0; i < layersStateObject.selection.length; i++)
            r.putIdentifier(s2t("layer"), layersStateObject.selection[i]);
        (d = new ActionDescriptor()).putReference(s2t("target"), r);
        d.putBoolean(s2t("makeVisible"), false);
        executeAction(s2t("select"), d, DialogModes.NO);
    } else {
        (r = new ActionReference()).putEnumerated(s2t("layer"), s2t('ordinal'), s2t('targetEnum'));
        (d = new ActionDescriptor()).putReference(s2t('target'), r);
        executeAction(s2t('selectNoLayers'), d, DialogModes.NO);
    }
}

 

 

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
Explorer ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

Wow, Stephen you must be a wizard! It works! These are just a couple of other things that are not critical, but I'm curious about your expertise if you have any thoughts on these. 

- For some of the layers I want to liquify, I'm looking to liquefy the mask on the layer instead of the layer contents. It doesn't seem like there is a way to select those to run the action on them without going one by one

- I would always want to use the same exact liquified mesh for all the layers. Does it need to 'load mesh' for each layer? That seems to be the slowest aspect of the script at the moment.

Either way, what you've created was supposedly impossible, and I'm really appreciative of your help with this!

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
Community Expert ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

quote

Wow, Stephen you must be a wizard! It works! These are just a couple of other things that are not critical, but I'm curious about your expertise if you have any thoughts on these. 

- For some of the layers I want to liquify, I'm looking to liquefy the mask on the layer instead of the layer contents. It doesn't seem like there is a way to select those to run the action on them without going one by one

 

Thanks for the kind words, most of the script was borrowed and repurposed code from jazz-y!

 

Thinking out loud, it should be simple enough to create a variation of the previous script that would select the layer mask and run liquify, rather than running on the layer. It would be assumed that the masks are raster, not vector.

 

quote

- I would always want to use the same exact liquified mesh for all the layers. Does it need to 'load mesh' for each layer? That seems to be the slowest aspect of the script at the moment.

Either way, what you've created was supposedly impossible, and I'm really appreciative of your help with this!


By @Tyler229371107i00

 

If I'm understanding you correctly, then yes, it uses the automatically saved last used mesh preset.

 

There is no magic here, the script is simply looping over all selected layers and running the same liquify mesh command again on each layer. The looping takes time, the liquify command takes time for each new layer.

 

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
Explorer ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

Sure, that makes sense regarding the loading of the mesh each time. I was just hoping there COULD be some magic time saving trick there. 

Your idea on having an alternate script that would select the mask of the layer to liquify instead of the main layer contents seems like an excellent way to approach it. It wouldn't be much trouble at all to run two scripts on the file. Once for all the normal layers and once for all the layers with the masks. All the masks I work with are raster, not vector. 

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
Community Expert ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

quote

Sure, that makes sense regarding the loading of the mesh each time. I was just hoping there COULD be some magic time saving trick there. 

 

Others may know better :]

 

 

quote

It wouldn't be much trouble at all to run two scripts on the file. Once for all the normal layers and once for all the layers with the masks. All the masks I work with are raster, not vector. 


By @Tyler229371107i00

 

As the script retains the original selections, you could just run the second script, I'd build in logic to gracefully handle layers without a mask.

 

One script could do both though in a single pass... However I'd still probably make a second script as proof of concept, before combining both.

 

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
Explorer ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

A single script would be a dream scenario! 😄

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
Community Expert ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

quote

A single script would be a dream scenario! 😄


By @Tyler229371107i00

 

Baby steps! :]

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
Community Expert ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

@Tyler229371107i00 

 

The following script can be run after the first script, it will liquify raster layer masks using the previously used mesh, ignoring the layer data which was previously liquified using the first script.

 

/*
Liquify Selected Layers Masks using Last Mesh.jsx
v1.0, 8th January 2024, Stephen Marsh
*/

#target photoshop

function main() {

    // Save the current dialog display settings
    var savedDisplayDialogs = app.displayDialogs;
    app.displayDialogs = DialogModes.NO;

    // Capture the initial layer visibility and layer selection
    var currentLayersState = getLayersVisiblity();

    // Get the selected layers: courtesy of jazz-y
    var s2t = stringIDToTypeID;
    (r = new ActionReference()).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
    r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
    var lrs = executeActionGet(r).getList(p),
        sel = new ActionReference();

    // Loop over the selected layers: courtesy of jazz-y
    for (var i = 0; i < lrs.count; i++) {
        sel.putIdentifier(s2t('layer'), p = lrs.getReference(i).getIdentifier(s2t('layerID')));
        (r = new ActionReference()).putIdentifier(s2t('layer'), p);
        (d = new ActionDescriptor()).putReference(s2t("target"), r);
        executeAction(s2t('select'), d, DialogModes.NO);

        // Raster mask, vector mask not currently supported
        if (hasLayerMask() === true) {
            // Select the mask
            selectLayerCompositeChannel("mask");
            // Apply the last liquify filter mesh
            var idLqFy = charIDToTypeID("LqFy");
            var desc213 = new ActionDescriptor();
            var idLqMD = charIDToTypeID("LqMD");
            desc213.putString(idLqMD, app.preferencesFolder.fsName + "/" + "Liquify Last Mesh.psp");
            executeAction(idLqFy, desc213, DialogModes.NO);
        }
    }
    // Finish the loop

    // Restore the initial layer visibility and selection
    setLayersVisiblity(currentLayersState);

    // Restore the dialogs
    app.displayDialogs = savedDisplayDialogs;

    app.beep();
    alert("Script completed!");
}

// Single history stage undo
activeDocument.suspendHistory("Liquify Selected Layers Masks using Last Mesh.jsx", "main()");


///// FUNCTIONS /////

function hasLayerMask() {
    // From Adobe's Flatten All Masks.jsx
    var hasLayerMask = false;
    try {
        var ref = new ActionReference();
        var keyUserMaskEnabled = app.charIDToTypeID('UsrM');
        ref.putProperty(app.charIDToTypeID('Prpr'), keyUserMaskEnabled);
        ref.putEnumerated(app.charIDToTypeID('Lyr '), app.charIDToTypeID('Ordn'), app.charIDToTypeID('Trgt'));
        var desc = executeActionGet(ref);
        if (desc.hasKey(keyUserMaskEnabled)) {
            hasLayerMask = true;
        }
    } catch (e) {
        hasLayerMask = false;
    }
    return hasLayerMask;
}

function selectLayerCompositeChannel(chanPara) {
    // "RGB" | "mask"
    var s2t = function (s) {
        return app.stringIDToTypeID(s);
    };
    var descriptor = new ActionDescriptor();
    var reference = new ActionReference();
    reference.putEnumerated(s2t("channel"), s2t("channel"), s2t(chanPara));
    descriptor.putReference(s2t("null"), reference);
    descriptor.putBoolean(s2t("makeVisible"), false);
    executeAction(s2t("select"), descriptor, DialogModes.NO);
}

function getLayersVisiblity() {
    // by jazz-y
    var s2t = stringIDToTypeID,
        t2s = typeIDToStringID;
    (r = new ActionReference()).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
    r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
    var targetLayers = executeActionGet(r).getList(p),
        seletion = [],
        visiblity = {};
    for (var i = 0; i < targetLayers.count; i++) seletion.push(targetLayers.getReference(i).getIdentifier());
    (r = new ActionReference()).putProperty(s2t('property'), p = s2t('numberOfLayers'));
    r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
    var len = executeActionGet(r).getInteger(p);
    for (var i = 1; i <= len; i++) {
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerSection'));
        r.putIndex(s2t('layer'), i);
        if (t2s(executeActionGet(r).getEnumerationValue(p)) == 'layerSectionEnd') continue;
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerID'));
        r.putIndex(s2t('layer'), i);
        var id = executeActionGet(r).getInteger(p);
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('visible'));
        r.putIndex(s2t('layer'), i);
        var visible = executeActionGet(r).getBoolean(p);
        visiblity[id] = visible;
    }
    return {
        selection: seletion,
        visiblity: visiblity
    };
}

function setLayersVisiblity(layersStateObject) {
    // by jazz-y
    var s2t = stringIDToTypeID;
    for (var a in layersStateObject.visiblity) {
        makeVisible = layersStateObject.visiblity[a] ? "show" : "hide";
        (r = new ActionReference()).putIdentifier(s2t('layer'), a);
        (d = new ActionDescriptor()).putReference(s2t('target'), r);
        executeAction(s2t(makeVisible), d, DialogModes.NO);
    }
    if (layersStateObject.selection.length) {
        var r = new ActionReference();
        for (var i = 0; i < layersStateObject.selection.length; i++)
            r.putIdentifier(s2t("layer"), layersStateObject.selection[i]);
        (d = new ActionDescriptor()).putReference(s2t("target"), r);
        d.putBoolean(s2t("makeVisible"), false);
        executeAction(s2t("select"), d, DialogModes.NO);
    } else {
        (r = new ActionReference()).putEnumerated(s2t("layer"), s2t('ordinal'), s2t('targetEnum'));
        (d = new ActionDescriptor()).putReference(s2t('target'), r);
        executeAction(s2t('selectNoLayers'), d, DialogModes.NO);
    }
}

 

 

The final step will be to combine both scripts into one.

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
Community Expert ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

@Tyler229371107i00 

 

The following script will apply the last used liquify mesh to all layers and layer masks in a single pass!

 

/*
Liquify Selected Layers & Masks using Last Mesh.jsx
v1.0, 8th January 2024, Stephen Marsh
*/

#target photoshop

function main() {

    // Save the current dialog display settings
    var savedDisplayDialogs = app.displayDialogs;
    app.displayDialogs = DialogModes.NO;

    // Capture the initial layer visibility and layer selection
    var currentLayersState = getLayersVisiblity();

    // Get the selected layers: courtesy of jazz-y
    var s2t = stringIDToTypeID;
    (r = new ActionReference()).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
    r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
    var lrs = executeActionGet(r).getList(p),
        sel = new ActionReference();

    // Loop over the selected layers: courtesy of jazz-y
    for (var i = 0; i < lrs.count; i++) {
        sel.putIdentifier(s2t('layer'), p = lrs.getReference(i).getIdentifier(s2t('layerID')));
        (r = new ActionReference()).putIdentifier(s2t('layer'), p);
        (d = new ActionDescriptor()).putReference(s2t("target"), r);
        executeAction(s2t('select'), d, DialogModes.NO);

        // Raster mask, vector mask not currently supported
        if (hasLayerMask() === true) {
            // Apply the last liquify filter mesh to the layer mask
            selectLayerCompositeChannel("mask");
            applyLastMesh();
        } else {
            // Apply the last liquify filter mesh
            applyLastMesh();
        }
    }
    // Finish the loop

    // Restore the initial layer visibility and selection
    setLayersVisiblity(currentLayersState);

    // Restore the dialogs
    app.displayDialogs = savedDisplayDialogs;

    app.beep();
    alert("Script completed!");
}

// Single history stage undo
activeDocument.suspendHistory("Liquify Selected Layers & Masks using Last Mesh.jsx", "main()");


///// FUNCTIONS /////

function hasLayerMask() {
    // From Adobe's Flatten All Masks.jsx
    var hasLayerMask = false;
    try {
        var ref = new ActionReference();
        var keyUserMaskEnabled = app.charIDToTypeID('UsrM');
        ref.putProperty(app.charIDToTypeID('Prpr'), keyUserMaskEnabled);
        ref.putEnumerated(app.charIDToTypeID('Lyr '), app.charIDToTypeID('Ordn'), app.charIDToTypeID('Trgt'));
        var desc = executeActionGet(ref);
        if (desc.hasKey(keyUserMaskEnabled)) {
            hasLayerMask = true;
        }
    } catch (e) {
        hasLayerMask = false;
    }
    return hasLayerMask;
}

function selectLayerCompositeChannel(chanPara) {
    // "RGB" | "mask"
    var s2t = function (s) {
        return app.stringIDToTypeID(s);
    };
    var descriptor = new ActionDescriptor();
    var reference = new ActionReference();
    reference.putEnumerated(s2t("channel"), s2t("channel"), s2t(chanPara));
    descriptor.putReference(s2t("null"), reference);
    descriptor.putBoolean(s2t("makeVisible"), false);
    executeAction(s2t("select"), descriptor, DialogModes.NO);
}

function getLayersVisiblity() {
    // by jazz-y
    var s2t = stringIDToTypeID,
        t2s = typeIDToStringID;
    (r = new ActionReference()).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
    r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
    var targetLayers = executeActionGet(r).getList(p),
        seletion = [],
        visiblity = {};
    for (var i = 0; i < targetLayers.count; i++) seletion.push(targetLayers.getReference(i).getIdentifier());
    (r = new ActionReference()).putProperty(s2t('property'), p = s2t('numberOfLayers'));
    r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
    var len = executeActionGet(r).getInteger(p);
    for (var i = 1; i <= len; i++) {
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerSection'));
        r.putIndex(s2t('layer'), i);
        if (t2s(executeActionGet(r).getEnumerationValue(p)) == 'layerSectionEnd') continue;
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerID'));
        r.putIndex(s2t('layer'), i);
        var id = executeActionGet(r).getInteger(p);
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('visible'));
        r.putIndex(s2t('layer'), i);
        var visible = executeActionGet(r).getBoolean(p);
        visiblity[id] = visible;
    }
    return {
        selection: seletion,
        visiblity: visiblity
    };
}

function setLayersVisiblity(layersStateObject) {
    // by jazz-y
    var s2t = stringIDToTypeID;
    for (var a in layersStateObject.visiblity) {
        makeVisible = layersStateObject.visiblity[a] ? "show" : "hide";
        (r = new ActionReference()).putIdentifier(s2t('layer'), a);
        (d = new ActionDescriptor()).putReference(s2t('target'), r);
        executeAction(s2t(makeVisible), d, DialogModes.NO);
    }
    if (layersStateObject.selection.length) {
        var r = new ActionReference();
        for (var i = 0; i < layersStateObject.selection.length; i++)
            r.putIdentifier(s2t("layer"), layersStateObject.selection[i]);
        (d = new ActionDescriptor()).putReference(s2t("target"), r);
        d.putBoolean(s2t("makeVisible"), false);
        executeAction(s2t("select"), d, DialogModes.NO);
    } else {
        (r = new ActionReference()).putEnumerated(s2t("layer"), s2t('ordinal'), s2t('targetEnum'));
        (d = new ActionDescriptor()).putReference(s2t('target'), r);
        executeAction(s2t('selectNoLayers'), d, DialogModes.NO);
    }
}

function applyLastMesh() {
    var idLqFy = charIDToTypeID("LqFy");
    var desc213 = new ActionDescriptor();
    var idLqMD = charIDToTypeID("LqMD");
    desc213.putString(idLqMD, app.preferencesFolder.fsName + "/" + "Liquify Last Mesh.psp");
    executeAction(idLqFy, desc213, DialogModes.NO);
}

 

 

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
Explorer ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

Stephen, this is insane. So if I'm understanding this correctly, there are three scripts as options here.

1 - Liquify layer contents for any selected layers

2 - Liquify mask contents for any selected layers

3 - Liquify layer and mask contents for any selected layers

Is that how it should work? =O

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
Community Expert ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

You got it! As you requested for the 3rd script, if the layer has a mask, only the mask is liquified, not the layer.

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
Explorer ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

Once again, I really appreciate your help on this! I owe you a can of Slurm! 😄

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
Community Expert ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

quote

Once again, I really appreciate your help on this! I owe you a can of Slurm! 😄


By @Tyler229371107i00

 

Please mark my 3rd script as a correct answer and we're all good!

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
Explorer ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

Done! Would it be a huge trouble to request one that does both the layer contents and the layer mask? That would actually cover every possible scenario. 

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
Community Expert ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

Sure, that's easy enough:

 

I put v2 at the end of the script name:

 

/*
Liquify Selected Layers & Masks using Last Mesh v2.jsx
v1.0, 8th January 2024, Stephen Marsh
*/

#target photoshop

function main() {

    // Save the current dialog display settings
    var savedDisplayDialogs = app.displayDialogs;
    app.displayDialogs = DialogModes.NO;

    // Capture the initial layer visibility and layer selection
    var currentLayersState = getLayersVisiblity();

    // Get the selected layers: courtesy of jazz-y
    var s2t = stringIDToTypeID;
    (r = new ActionReference()).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
    r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
    var lrs = executeActionGet(r).getList(p),
        sel = new ActionReference();

    // Loop over the selected layers: courtesy of jazz-y
    for (var i = 0; i < lrs.count; i++) {
        sel.putIdentifier(s2t('layer'), p = lrs.getReference(i).getIdentifier(s2t('layerID')));
        (r = new ActionReference()).putIdentifier(s2t('layer'), p);
        (d = new ActionDescriptor()).putReference(s2t("target"), r);
        executeAction(s2t('select'), d, DialogModes.NO);

        // Raster mask, vector mask not currently supported
        if (hasLayerMask() === true) {
            // Apply the last liquify filter mesh
            applyLastMesh();
            // Apply the last liquify filter mesh to the layer mask
            selectLayerCompositeChannel("mask");
            applyLastMesh();
        } else {
            // Apply the last liquify filter mesh
            applyLastMesh();
        }
    }
    // Finish the loop

    // Restore the initial layer visibility and selection
    setLayersVisiblity(currentLayersState);

    // Restore the dialogs
    app.displayDialogs = savedDisplayDialogs;

    app.beep();
    alert("Script completed!");
}

// Single history stage undo
activeDocument.suspendHistory("Liquify Selected Layers & Masks using Last Mesh v2.jsx", "main()");


///// FUNCTIONS /////

function hasLayerMask() {
    // From Adobe's Flatten All Masks.jsx
    var hasLayerMask = false;
    try {
        var ref = new ActionReference();
        var keyUserMaskEnabled = app.charIDToTypeID('UsrM');
        ref.putProperty(app.charIDToTypeID('Prpr'), keyUserMaskEnabled);
        ref.putEnumerated(app.charIDToTypeID('Lyr '), app.charIDToTypeID('Ordn'), app.charIDToTypeID('Trgt'));
        var desc = executeActionGet(ref);
        if (desc.hasKey(keyUserMaskEnabled)) {
            hasLayerMask = true;
        }
    } catch (e) {
        hasLayerMask = false;
    }
    return hasLayerMask;
}

function selectLayerCompositeChannel(chanPara) {
    // "RGB" | "mask"
    var s2t = function (s) {
        return app.stringIDToTypeID(s);
    };
    var descriptor = new ActionDescriptor();
    var reference = new ActionReference();
    reference.putEnumerated(s2t("channel"), s2t("channel"), s2t(chanPara));
    descriptor.putReference(s2t("null"), reference);
    descriptor.putBoolean(s2t("makeVisible"), false);
    executeAction(s2t("select"), descriptor, DialogModes.NO);
}

function getLayersVisiblity() {
    // by jazz-y
    var s2t = stringIDToTypeID,
        t2s = typeIDToStringID;
    (r = new ActionReference()).putProperty(s2t('property'), p = s2t('targetLayersIDs'));
    r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
    var targetLayers = executeActionGet(r).getList(p),
        seletion = [],
        visiblity = {};
    for (var i = 0; i < targetLayers.count; i++) seletion.push(targetLayers.getReference(i).getIdentifier());
    (r = new ActionReference()).putProperty(s2t('property'), p = s2t('numberOfLayers'));
    r.putEnumerated(s2t('document'), s2t('ordinal'), s2t('targetEnum'));
    var len = executeActionGet(r).getInteger(p);
    for (var i = 1; i <= len; i++) {
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerSection'));
        r.putIndex(s2t('layer'), i);
        if (t2s(executeActionGet(r).getEnumerationValue(p)) == 'layerSectionEnd') continue;
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('layerID'));
        r.putIndex(s2t('layer'), i);
        var id = executeActionGet(r).getInteger(p);
        (r = new ActionReference()).putProperty(s2t('property'), p = s2t('visible'));
        r.putIndex(s2t('layer'), i);
        var visible = executeActionGet(r).getBoolean(p);
        visiblity[id] = visible;
    }
    return {
        selection: seletion,
        visiblity: visiblity
    };
}

function setLayersVisiblity(layersStateObject) {
    // by jazz-y
    var s2t = stringIDToTypeID;
    for (var a in layersStateObject.visiblity) {
        makeVisible = layersStateObject.visiblity[a] ? "show" : "hide";
        (r = new ActionReference()).putIdentifier(s2t('layer'), a);
        (d = new ActionDescriptor()).putReference(s2t('target'), r);
        executeAction(s2t(makeVisible), d, DialogModes.NO);
    }
    if (layersStateObject.selection.length) {
        var r = new ActionReference();
        for (var i = 0; i < layersStateObject.selection.length; i++)
            r.putIdentifier(s2t("layer"), layersStateObject.selection[i]);
        (d = new ActionDescriptor()).putReference(s2t("target"), r);
        d.putBoolean(s2t("makeVisible"), false);
        executeAction(s2t("select"), d, DialogModes.NO);
    } else {
        (r = new ActionReference()).putEnumerated(s2t("layer"), s2t('ordinal'), s2t('targetEnum'));
        (d = new ActionDescriptor()).putReference(s2t('target'), r);
        executeAction(s2t('selectNoLayers'), d, DialogModes.NO);
    }
}

function applyLastMesh() {
    var idLqFy = charIDToTypeID("LqFy");
    var desc213 = new ActionDescriptor();
    var idLqMD = charIDToTypeID("LqMD");
    desc213.putString(idLqMD, app.preferencesFolder.fsName + "/" + "Liquify Last Mesh.psp");
    executeAction(idLqFy, desc213, DialogModes.NO);
}

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
Explorer ,
Jan 07, 2024 Jan 07, 2024

Copy link to clipboard

Copied

LATEST

Wizardly!

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