Reputation: 1
I'm looking into getting into generative art. My idea is to have Photoshop (CS5) generate a unique PNG for all permutations that exist while the script iterates through every LAYER across each LAYER GROUP (layerSets).
As an example, it would be similar to a character generator where: PARENT layerSets consist of parts or locations across the face/body (A,B) CHILD layers consist of accessories/styles (1,2,3) Such that all generated PNG permutations would be: A1B1,A2B1,A3B1;A2B1,A2B2,A2B3;A3B1,A3B2,A3B3 only. (A1A2, A2A3, A1A3; B1B2, B2B3, B1B3 are not necessary; Standalone A1,A2,A3,B1,B2,B3 are not necessary).
I've found some code from @Mr.Online that generates random, and potentially redundant combinations from user-inputted quantity. His script requires that all layers be hidden by the user prior to running.
Thanks so much. Hopefully this'll help:
function Visible() {
var Grps = app.activeDocument.layerSets; // loops through all groups
for(var i = 0; i < Grps.length; i++){
var tmp = app.activeDocument.layerSets[i].layers.length;
app.activeDocument.layerSets[i].visible=true;
var groupChildArr = app.activeDocument.layerSets[i].layers;
var randLays = Math.floor(Math.random() * tmp);
groupChildArr[randLays].visible = true;
Save();
}
Revert();
}
function Save() {
var outFolder = app.activeDocument; // psd name
var outPath = outFolder.path;
var fName = "PNG"; // define folder name
var f = new Folder(outPath + "/" + fName);
if ( ! f.exists ) {
f.create()
}
var saveFile = new File(outPath + "/" + fName +"/" + "Pattern_" + num + ".png");
pngSaveOptions = new PNGSaveOptions();
pngSaveOptions.interlaced = false;
app.activeDocument.saveAs(saveFile, pngSaveOptions, true, Extension.LOWERCASE);
}
// Original code - revert function does not work
// for some users
//function Revert(){
// var idslct = charIDToTypeID( "slct" );
// var desc300 = new ActionDescriptor();
// var idnull = charIDToTypeID( "null" );
// var ref163 = new ActionReference();
// var idSnpS = charIDToTypeID( "SnpS" );
// ref163.putName( idSnpS, "test.psd" );
// desc300.putReference( idnull, ref163 );
// executeAction( idslct, desc300, DialogModes.NO );
//}
function Revert(){
var idRvrt = charIDToTypeID( "Rvrt" );
executeAction( idRvrt, undefined, DialogModes.NO );
}
var count = prompt("How many patterns you want","");
for (var x=0 ; x<count;x++){
var num = x+1;
Visible();
}
Upvotes: 0
Views: 332
Reputation: 6967
As you say, you need to ignore the random layers. However, if you know the number of layers & groups it's quite straight forward:
show_layers("A", "1");
show_layers("B", "1");
function show_layers(g, n)
{
// g is the name of the group (layerset)
// n is the name of the layer (artlayer)
srcDoc.activeLayer = srcDoc.layerSets.getByName(g).artLayers.getByName(n);
srcDoc.activeLayer.visible = true;
}
So, assuming all layers are switched off, you can get the layers by name and then make them visible.
Switching off all the layers is a bit more involved. You have to loop over all groups and then loop over its sublayers. Working with groups is a bit of a learning curve.
function switch_off_all_layers(bool)
{
var numLayers = app.activeDocument.layers.length;
// want to hide the background as well?
// default: background = visible
if (bool == undefined) bool = false;
if (bool == false)
{
numLayers -=1; // -1 for background
}
for(var i = 0 ; i < numLayers; i++)
{
if (app.activeDocument.layers[i].typename == "LayerSet")
{
app.activeDocument.layers[i].visible = true;
var subDoc = app.activeDocument.layers[i];
var numOfSubLayers = subDoc.layers.length;
for (var j = numOfSubLayers -1; j >= 0; j--)
{
var tempSubLayer = subDoc.layers[j];
tempSubLayer.visible = false;
}
}
}
}
Further to my explanation, if you can't supply the group layers & names then you fill want to loop over all groups and all layers.
var groupLayers = [];
var artLayers = [];
var theLayers = collectAllLayers(app.activeDocument, 0);
alert("Group layers\n" + groupLayers);
alert("Art layers\n" + artLayers);
// function collect all layers
function collectAllLayers (theParent, level)
{
for (var m = theParent.layers.length - 1; m >= 0; m--)
{
var theLayer = theParent.layers[m];
// apply the function to layersets;
if (theLayer.typename == "ArtLayer")
{
if (theLayer.isBackgroundLayer == true)
{
// add background layer (if needed)
// artLayers.push(theLayer.name);
}
else
{
// find the art layers
artLayers.push(theLayer.name);
}
}
else
{
// find the group layers
groupLayers.push(theLayer.name);
collectAllLayers(theLayer, level + 1)
}
}
}
Upvotes: 0