johnjoeparrot
Explorer
johnjoeparrot
Explorer
Activity
‎Feb 26, 2025
08:10 PM
2 Upvotes
This is perfect, thanks for your time!
... View more
‎Feb 26, 2025
05:22 PM
Hello, Is there a way to find all active layers with JSX? The 'doc.activeLayer' function seems to target only the first activeLayer in the layer panel Thanks  
... View more
‎Nov 08, 2024
06:35 PM
1 Upvote
This is great insights, thanks @c.pfaffenbichler & @Stephen Marsh. I didn't konw about the make frame from layers feature I find that if the animation has to many frames the 'Save for Web window' doesn't open but if I use the script the GIF exports eventually I'm getting close with the script. It creates a frame by frame animation and exports beside the PSD. The last bit I need to work on is the blank frame on the end frame and the duplicate file stays open I'll keep working on it I've attached an example of an export and added the working progess edited script that was used for the export // create gif with the layers added one at a time;
// 2020, use it at your own risk;
if (app.documents.length > 0) {
var thisDoc = app.activeDocument;
try {
var theName = thisDoc.name.match(/(.*)\.[^\.]+$/)[1];
var thePath = thisDoc.path
} catch (e) {
var theName = thisDoc.name;
var thePath = "~/Desktop"
};
// make duplicate;
var myDocument = thisDoc.duplicate();
// =======================================================
var idmakeFrameAnimation = stringIDToTypeID("makeFrameAnimation");
executeAction(idmakeFrameAnimation, undefined, DialogModes.NO);
setFrameDelay(0);
// hide all but lowermost layer;
// collect layers;
var theLayers = collectLayersBounds();
// alert(app.documents.length.length)
hideOthers(myDocument.activeLayer, myDocument);
// add frames;
var frame;
for (var a = 0; a < theLayers.length; a++) {
// =======================================================
var desc2 = new ActionDescriptor();
var ref1 = new ActionReference();
showLayer(theLayers[a][1], false);
ref1.putEnumerated(stringIDToTypeID("animationFrameClass"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
desc2.putReference(charIDToTypeID("null"), ref1);
executeAction(charIDToTypeID("Dplc"), desc2, DialogModes.NO);
// show;
frame = thisDoc.layers[a];
// alert(theLayers[a])
showLayer(theLayers[a][1], true);
// hideOthers (myDocument.layers[myDocument.layers.length - 1], myDocument);
};
// export;
exportGif(thePath, theName + ".gif");
// close copy;
myDocument.close(SaveOptions.DONOTSAVECHANGES)
};
////////////////////////////////////
////// set framedelay //////
function setFrameDelay(theDelay) {
try {
var desc14 = new ActionDescriptor();
var ref7 = new ActionReference();
ref7.putEnumerated(stringIDToTypeID("animationFrameClass"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
desc14.putReference(charIDToTypeID("null"), ref7);
var desc15 = new ActionDescriptor();
desc15.putDouble(stringIDToTypeID("animationFrameDelay"), theDelay);
desc14.putObject(charIDToTypeID("T "), stringIDToTypeID("animationFrameClass"), desc15);
executeAction(charIDToTypeID("setd"), desc14, DialogModes.NO);
return true
} catch (e) {
return false
}
};
////// collect layers //////
function collectLayersBounds() {
// the file;
var myDocument = app.activeDocument;
// get number of layers;
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
var theLayers = new Array;
var frame = numberToString(theNumber)
for (var m = 0; m < theNumber; m++) {
try {
// alert(theNumber - m)
var ref = new ActionReference();
ref.putIndex(charIDToTypeID("Lyr "), theNumber - m);
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// alert(isBackground)
// if group collect values;
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart" && isBackground != true) {
// var theName = layerDesc.getString(stringIDToTypeID('name'));
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
// var oooooo = reverseString(stringIDToTypeID('layerID'));
// alert(reverseString(layerSet))
var theBounds = layerDesc.getObjectValue(stringIDToTypeID("bounds"));
var theseBounds = [theBounds.getUnitDoubleValue(stringIDToTypeID("left")), theBounds.getUnitDoubleValue(stringIDToTypeID("top")), theBounds.getUnitDoubleValue(stringIDToTypeID("right")), theBounds.getUnitDoubleValue(stringIDToTypeID("bottom"))];
// var theseBounds = m;
theLayers.push([theName, theID, theseBounds])
};
} catch (e) {};
};
return theLayers
};
function numberToString(b) {
var a = [];
for (var i = 0; i < b; i++) {
a.push(i);
}
return a;
}
function reverseString(str) {
// Step 1. Use the split() method to return a new array
var splitString = str.split(""); // var splitString = "hello".split("");
// ["h", "e", "l", "l", "o"]
// Step 2. Use the reverse() method to reverse the new created array
var reverseArray = splitString.reverse(); // var reverseArray = ["h", "e", "l", "l", "o"].reverse();
// ["o", "l", "l", "e", "h"]
// Step 3. Use the join() method to join all elements of the array into a string
var joinArray = reverseArray.join(""); // var joinArray = ["o", "l", "l", "e", "h"].join("");
// "olleh"
//Step 4. Return the reversed string
return joinArray; // "olleh"
}
////// toggle visibility of others //////
function hideOthers(theLayer, myDocument) {
myDocument.activeLayer = theLayer;
// =======================================================
var desc10 = new ActionDescriptor();
var list4 = new ActionList();
var ref7 = new ActionReference();
ref7.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
list4.putReference(ref7);
desc10.putList(charIDToTypeID("null"), list4);
desc10.putBoolean(charIDToTypeID("TglO"), true);
executeAction(charIDToTypeID("Shw "), desc10, DialogModes.NO);
};
////// show layer //////
function showLayer(theID, showOrHide) {
if (showOrHide == false) {
var idHd = charIDToTypeID("Shw ")
}
else {
var idHd = charIDToTypeID("Hd ")
};
var desc2 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
var list1 = new ActionList();
var ref1 = new ActionReference();
ref1.putIdentifier(charIDToTypeID("Lyr "), theID);
list1.putReference(ref1);
desc2.putList(idnull, list1);
executeAction(idHd, desc2, DialogModes.NO);
};
////// export gif //////
function exportGif(thePath, theName) {
var webOptions = new ExportOptionsSaveForWeb();
webOptions.format = SaveDocumentType.COMPUSERVEGIF;
// webOptions.transparency = true;
// webOptions.interlaced = true;
// webOptions.includeProfile = false;
// webOptions.quality = 100;
// webOptions.matteType = 'NONE';
// webOptions.colors = 258;
// webOptions.optimized = true;
activeDocument.exportDocument(new File(thePath + "/" + theName), ExportType.SAVEFORWEB, webOptions);
};
... View more
‎Nov 07, 2024
11:13 PM
1 Upvote
Thank you!
... View more
‎Nov 07, 2024
09:11 AM
What is the recommended way to set up development environment to write scripts for adobe products? My process right now is to create a jsx, run the script with an action and use the alert function to log information. This is limiting cause I can't log the scope of objects and test before a infinite loop. Thanks
... View more
‎Nov 06, 2024
07:35 PM
1 Upvote
I've adjusted the code a bit to check to see if there is a mask and if it doesn't apply mask to that layer app.activeDocument.suspendHistory('Add reveal all layer mask to top-level layers...', 'setLayersWithMask()');
function setLayersWithMask() {
// Capture the initial layer visibility and layer selection
var currentLayersState = getLayersVisiblity();
// Ensure that a layer is selected
try {
activeDocument.activeLayer.link(activeDocument.activeLayer);
} catch (e) { }
// Loop over the root/top-level layers (change artLayers to layers to include groups)
for (var i = 0; i < app.activeDocument.artLayers.length; i++) {
app.activeDocument.activeLayer = activeDocument.artLayers[i];
if(!hasChannelMaskByName(app.activeDocument.layers[i].name)){
addMask();
}
}
function addMask(apply){
// by Stephen_A_Marsh
if (apply == undefined) apply = false;
try
{
// Add a reveal all layer mask to the layer
function s2t(s) {
return app.stringIDToTypeID(s);
}
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
descriptor.putClass(s2t("new"), s2t("channel"));
reference.putEnumerated(s2t("channel"), s2t("channel"), s2t("mask"));
descriptor.putReference(s2t("at"), reference);
descriptor.putEnumerated(s2t("using"), s2t("userMaskEnabled"), s2t("revealAll"));
executeAction(s2t("make"), descriptor, DialogModes.NO);
return true
}
catch (e)
{
return false
}
}
/**
* deletes layer mask from active layer
* @Param if apply is true, mask will be applied, if false — mask will be discarded
* @Return boolean
*/
function deleteMask(apply)
{
if (apply == undefined) apply = false;
try
{
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated(charIDToTypeID('Chnl'), charIDToTypeID('Chnl'), charIDToTypeID('Msk '));
desc.putReference(charIDToTypeID('null'), ref);
desc.putBoolean(charIDToTypeID('Aply'), apply);
executeAction(charIDToTypeID('Dlt '), desc, DialogModes.NO);
return true
}
catch (e)
{
return false
}
};
function hasChannelMaskByName( layerName ){
// by Michael_L_Hale
var ref = new ActionReference();
ref.putName( charIDToTypeID( "Lyr " ), layerName );
return executeActionGet( ref ).getBoolean( stringIDToTypeID( 'hasUserMask' ) );
}
// Restore the initial layer visibility and selection
setLayersVisiblity(currentLayersState);
//// 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);
}
}
}
... View more
‎Nov 06, 2024
04:24 PM
1 Upvote
This is wild, thanks! I'm going to study this code, much appreciated This JSX feature works awesome with Generate Image Assets plugin
... View more
‎Nov 06, 2024
04:13 PM
Correct it would be a series of layers stacked onto of each other exported as a frame by frame gif. I do agree that it is a regular animation and could be achieved with actions. I'm looking for a JSX solution because of the benifit it provides I'll keep playing around with the code, I'm getting close to figureing it out
... View more
‎Nov 06, 2024
12:45 PM
Hello, I keep getting errors when creating a layer mask using photoshop JSX script I'm looking for a way to loop through all the layers and add a layer mask at the size of the document canvas. Here are the functions I am running but I can't figure out how to get it up and running Thanks for your time // loop through each layer
function walkLayers(o) {
var i;
var layer;
var frame;
var psd_name = decodeURI(app.activeDocument.name);
var file_name = psd_name.substring(0, psd_name.lastIndexOf('.')) || psd_name;
for (i = 0; i < o.layers.length; i++) {
layer = o.layers[i];
layer.name = file_name;
applyLayerMask(layer)
}
}
// Layer mask from selection
function applyLayerMask(layer) {
app.activeDocument.selection.selectAll(); // select entire canvas
// create a mask on layer
var c2t = function (s) {
return app.charIDToTypeID(s);
};
var s2t = function (s) {
return app.stringIDToTypeID(s);
};
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
descriptor.putClass( s2t( "new" ), s2t( "channel" ));
reference.putEnumerated( s2t( "channel" ), s2t( "channel" ), s2t( "mask" ));
descriptor.putReference( s2t( "at" ), reference );
descriptor.putEnumerated( s2t( "using" ), c2t( "UsrM" ), s2t( "revealSelection" ));
executeAction( s2t( "make" ), descriptor, DialogModes.NO );
}
walkLayers(app.activeDocument);
... View more
‎Nov 03, 2024
05:16 PM
Hello @c.pfaffenbichler Any tips for updateing the code to save the gif layer by layer? Instead of seeing all the previous layers in the animation it just shows each layer as a frame Thanks!
... View more
‎Feb 14, 2024
12:25 AM
1 Upvote
If I start at adobe.com how do I get to Kyle's brushes?
... View more
‎Feb 14, 2024
12:00 AM
1 Upvote
The link works, there is no way to get to the link without the link
... View more
‎Feb 13, 2024
11:32 PM
1 Upvote
There is no way to access Kyle's Brushes on the main adobe page Kyles brushes are available to Adobe Photoshop and Adobe Fresco subscribers but there is no way to download them without contacting support.
... View more
‎Feb 07, 2023
12:31 AM
1 Upvote
I uploaded a .psdt photoshop template file to Window > Libraries and it works perfectly. Each time I open a new document it creates a Untitled document from the template in the library. Thanks @PECourtejoie ! This is a game changing production efficiency.
... View more
‎Feb 06, 2023
09:15 PM
Hello @PECourtejoie , This is very helpful thank you! Is there a option for this to be applied to files in the cloud? I have photoshop on different devices
... View more
‎Feb 05, 2023
06:31 AM
Hello, I'd like to request for files on cloud to be available when starting a documnet preset. Current Workflow: When I start a animation project I need a new X Sheet and File with specific folder structure for every project. My current process files are stored locally, duplicated then used as template document preset. Requesting for the following: File > New Document > Saved > Select File as Document Preset Thanks
... View more