1 Reply Latest reply on Jun 7, 2018 6:15 AM by Tomas Sinkunas

    Trying to recursively loop through comp to find all color controls

    Tom Scharstein II Level 2

      Hey guys, new to scripting. I'd like to be able to crawl through my comp and identify any visible color controls (whether inside stroke or fill, for text, or color expression controls, etc.) to either .push() into an array or to modify each by appending an expression to it. I've modified snippets given by Horshack and Dan Ebberts (thanks btw!) and am successfully combing through every property of every layer of my comp, but I'm also returning hidden colors that I'd like to not have plus I'm getting some odd errors:


      //  find / replace parameters are for names, not relevant at the moment
      // main("Stroke 1", "Stroke");
      var count = 0;
      var colorArray = [];
      // Horshack @https://forums.adobe.com/thread/2317720
      function dumpPropTree(rootObj, nestingLevel, find, replace) {
          var countProps = rootObj.numProperties;
          for (var propIndex=1; propIndex <= countProps; propIndex++) {
              var prop = rootObj.property(propIndex);
              if (prop.name === find) {
                prop.name = replace;
              var type = prop.propertyValueType;
        /////// Color:
              switch(prop.propertyValueType) {
                case PropertyValueType.COLOR:
                  if (prop.canSetExpression) {
                    var newColor = rgbToHex(prop.value[0] * 255, prop.value[1] * 255, prop.value[2] * 255);
                     // working:
                    // alert(newColor);
                     // not working:
                    // colorArray.push(newColor);
        /////// End color
              if (prop.numProperties > 0)
                  dumpPropTree(prop, nestingLevel+1, find, replace);
      function main(find, replace) {
        var activeComp = app.project.activeItem;
        var countSelectedLayers = activeComp.layers.length;
        for (selectedLayerIndex = 1; selectedLayerIndex <= countSelectedLayers; selectedLayerIndex++) {
            var layer = activeComp.layers[selectedLayerIndex];
            dumpPropTree(layer, 0, find, replace);
        // alert("Result is " + colorArray);  // ERROR: Invalid numeric result (divide by zero?)
              // But why? There's no division in this code, and hex values are showing correctly?
      /// https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
      // componentToHex();
      // rgbToHex();


      When I use this on a comp that has one shape layer with 4 rectangles (each of which having one distinct fill), then I return 13 colors instead of 4, and the extras seem to be for Blending Modes because they're pure white or pure black. I thought .canSetExpression would filter those out since they don't seem to be visible, is there a better way to identify only the visible Color properties, and can I have any pointers on why I'm getting errors trying to push these hex values to a global array? The ideal output  would be returning an array like ["ff0000", "00aa99", "bcbcbc", "323232"], which would be all four (fill/stroke/expression control) colors currently inside my comp.


      Can I get any help here? I can discriminate the array so only new colors are added to prevent duplicates on my own, but I'm unsure why pushing to this array doesn't work here and how to get only visible colors (and would need these solved before moving on).

        • 1. Re: Trying to recursively loop through comp to find all color controls
          Tomas Sinkunas Adobe Community Professional

          Hey Tom. Wellcome to the club!


          alert("Result is " + colorArray); throws error because you are concatinating String with Array, witch is a bit nonono in JS land. To fix this, all you need to do is convert array to string, like so:

          alert("Result is " + colorArray.toString());


          To answer your quesstion regarding Hidden properties, I have this method, that tries to apply expression to a property (check function isHidden()). If it succeeds - then the property is hidden, if it fails - property is visible. We all wish there were an API to check if property is hidden, but there isn't;


          Also I have this snippet that retrieves all visible colors from a selected layer. I collect them all into an array colorProperties and then can do what ever I like with them, like adding expressions or whatever (not included in the snippet)


          Anyways, I hope this helps you out.





          (function() {
              var composition = app.project.activeItem;
              if (!composition || !(composition instanceof CompItem)) {
                  return alert("Please select composition first");
              var layer = composition.selectedLayers[0];
              if (!layer) {
                  return alert('Please select a layer');
              var colorProperties = getProperties(layer, isVisibleColorPropery);
              alert("Found " + colorProperties.length + " properties:\n" + colorProperties.join('\n'));
              function isVisibleColorPropery(property) {
                  return  property.propertyValueType === PropertyValueType.COLOR && !isHidden(property);
              function isHidden(property) {
                  var oldExpression = property.expression;
                  try {
                      // try to add some dummy expression;
                      // If it errors out - this means property is hidden
                      // overwise property can be modified
                      property.expression = "some dummy expression;";
                  } catch (e) {
                      return true;
                  // Set expression to it's old value;
                  property.expression = oldExpression;
                  return false;
              function getProperties(property, callback, colorProperties) {
                  colorProperties = colorProperties || [];
                  var curProperty;
                  for (var i = 1, il = property.numProperties; i <= il; i++) {
                      curProperty = property.property(i);
                      if (callback(curProperty)) {
                      getProperties(curProperty, callback, colorProperties);
                  return colorProperties;
          2 people found this helpful