Search code examples
photoshopphotoshop-script

Turning Multiple Layers On and Off in Photoshop Script


I have 6 groups in Photoshop that contain a number of layers within each group. I'm looking to turn on/off a layer within each group to create every possible combination of the image.

Can someone point me in the right direction?

I've never scripted in Photoshop but trying to figure this out on my own.


Solution

  • I'm quite new to CS5 scripting myself, but I think I can explain how it works. The code examples may not be the most effective way to do it, but it does the trick.

    There is a big difference between a Group of layers or the individual layer itself. All layers and groups are ordered in the DOM format. To get your root you can use the global instance app to get the active document: app.activeDocument.

    The messy part is that there are two separate arrays for single layers and groups. To get the array of single layers use app.activeDocument.layers and app.activeDocument.layerSets for the groups.

    To go deeper down in the hieralcy, use the layerSets array to iterate down.

    For example, let us assume the following hieralcy:

    -Border
    +Icons
       +Left
           -Star
           -Home
       +Right
           -Add
           -Remove
    

    Here Border, Star, Home, Add and Remove are all single layers while Icons, Left and Right are Groups.

    To turn on group Left we need to iterate down the Icon group:

    Icons = app.activeDocument.layerSets.getByName("Icons");
    Left = Icons.layerSets.getByName("Left");
    Left.visible = true;
    

    If you show a layer/group in CS5 by clicking with your mouse, all parent groups will automatically be shown too. By scripting this isn't the case, you have to enable all parents as well.

    Icons = app.activeDocument.layerSets.getByName("Icons");
    Icons.visible = true;
    Left = Icons.layerSets.getByName("Left");
    Left.visible = true;
    

    To show the Border layer you need to use the layers array instead.

    app.activeDocument.layers.getByName("Border").visible = true;
    

    Same things apply if you want to show the Add layer.

    Icons = app.activeDocument.layerSets.getByName("Icons");
    Icons.visible = true;
    Right = Icons.layerSets.getByName("Right");
    Right.visible = true;
    AddLayer = Right.layers.getByName("Add");
    AddLayer.visible = true;
    

    This can be a bit messy if you have a lot of groups and layers. I created a function that follows a supplied path to get the end object. It will determine by itself if it is a layer or a group.

    //******************************************
    // GET BY PATH
    // Author: Max Kielland
    //
    // Gets the LayerSet or Layer at the path's end.
    // Example path "Icons/left" will return the LayerSet object "Left"
    // while "Icons/left/Star" will return the Layer object "Star"
    // If fSetPath is true, all the parents will be visible as well.
    
    function GetByPath(fPath,fSetPath) {
    
      var lGroup = null;
      var lPathArray = new Array();
    
      lPathArray = fPath.split('/');
      try {
        lGroup = app.activeDocument.layers.getByName(lPathArray[0]);
      } catch (err) {
        lGroup = app.activeDocument.layerSets.getByName(lPathArray[0]);
      }
    
      if (fSetPath)
        lGroup.visible = true;
    
      for (n=1; n<lPathArray.length; n++) {
        try {
          lGroup = lGroup.layerSets.getByName(lPathArray[n]);
        } catch(err) {
          lGroup = lGroup.layers.getByName(lPathArray[n]);
        }
        if (fSetPath == true)
          lGroup.visible = true;
      }
    
      return lGroup;
    }
    

    ...and one function to simply set or clear a group or layer by its path.

    //******************************************
    // SET STATUS
    // Author: Max Kielland
    //
    // Sets the Group or Layer's visible property
    // at the end of the path to fStatus.
    
    function SetStatus(fPath, fStatus) {
    
      Obj = GetByPath(fPath,false);
      Obj.visible = fStatus;
    }
    

    ..and at last I wrote this function to hide all groups and/or layers from a user specified root.

    /******************************************
    // CLEAR GROUP
    // Author: Max Kielland
    //
    // Clears the visible property in a single
    // group/layer with the option to clear all
    // its children as well (fRecurs = true).
    // fLayerSet can be a layerSet object or a
    // String path.
    
    function ClearGroup(fLayerSet,fRecurs) {
    
      var n;
      var TargetGroup;
    
      // Get LayerSet Object if reference is a string.
      if (typeof fLayerSet == "string")
        TargetGroup = GetByPath(fLayerSet);
      else
        TargetGroup = fLayerSet;
    
      // Iterate through all LayerSets
      for (n=0; n<TargetGroup.layerSets.length; n++) {
        if (fRecurs == true)
          ClearGroup(TargetGroup.layerSets[n],true);
        else
         TargetGroup.layerSets[n].visible = false;
      }
    
      // Iterate through all layers
      for (n=0; n<TargetGroup.layers.length; n++) {
        TargetGroup.layers[n].visible = false;
      }
    
      // Clear self
      TargetGroup.visible = false;
    }
    

    Here is an example of how to use the functions

    // Hide group "Icon" and its children
    ClearGroup("Icons",true);
    
    //Show the layer "Home"
    GetByPath("Icons/Left/Home",true);
    
    // To just get the object "Right"
    var MyGroup = GetByPath("Icons/Right");
    
    // Save the current document as a PNG file
    app.activeDocument.saveAs(File("Scripted Document.png"),PNGSaveOptions);
    

    I hope this is useful to someone more than just me :)