Skip to main content
zsaaro
Inspiring
April 7, 2021
Answered

Calling the After-Effects color picker through script?

  • April 7, 2021
  • 4 replies
  • 3984 views

Hello!

Is there a way to actually call the regular After-Effects color picker through extendscript?

$.colorPicker() seem to ignore the "Use System Color Picker" pref and always uses the ms-paint style one.

Here's an example of it working: https://youtu.be/gtewHvmykIk?t=168

 

I can't find anything in the documentation and I can't seem to find a lot of info about this.

It's really important because the windows system color picker actually can't pick colors.

Thank you.

 

 

Saar

Correct answer _Sa
function GoodBoyNinjaColorPicker(startValue){
  // find the active comp
  var crntComp = app.project.activeItem;
  if (!crntComp || !(crntComp instanceof CompItem)) {
    alert("Please open a comp first");
    return [];
  }

  // add a temp null;
  var newNull = crntComp.layers.addNull();
  var newColorControl = newNull("ADBE Effect Parade").addProperty("ADBE Color Control");
  var theColorProp = newColorControl("ADBE Color Control-0001");

  // set the value given by the function arguments
  if (startValue && startValue.length == 3) {
    theColorProp.setValue(startValue);
  }

  // prepare to execute
  var editValueID = 2240 // or app.findMenuCommandId("Edit Value...");
  theColorProp.selected = true;
  app.executeCommand(editValueID);

  // harvest the result
  var result = theColorProp.value;

  // remove the null
  if (newNull) {
    newNull.remove();
  }

  return result;
}

// launch the true color picker with a white color
alert(GoodBoyNinjaColorPicker([1,1,1]));

 

This seem to do the trick. Could use some more error checking, also it takes an array of size 3 for the default value and returns an array of size 4 cause the harvested color has an alpha channel. If somebody wants to use it and make it feel even nicer you could make the new null a shy and turn on shy layers for the comp (but don't just turn it off later because the user could have it on to begin with, instead store the original state and revert to it).

 

Hope it helps someone.

Bye!

 

 

4 replies

Known Participant
January 18, 2024

Does anyone know out how to group that in an undo group:

app.beginUndoGroup("pick color");
app.endUndoGroup();

Otherwise, if you undo the action, you have to undo many single steps.
but 

 

var editValueID = 2240
app.executeCommand(editValueID);

 

inside the group seems to break the group logic somehow.
It produces error messages and many time it crashes AE in my case.
 
Known Participant
September 20, 2023

Thanks so much GoodBoyNinja
Thats so cool and clever.

I added some lines, because the layer selection gets destroyed with this method. So I stored it and restored at the end of the script.

function GoodBoyNinjaColorPicker(startValue){
    if(!startValue || startValue.length != 3){
      startValue = [1, 1, 1]; // default value
    }
  
    var comp = app.project.activeItem;
    if(!comp || !(comp instanceof CompItem)){
      alert("No comp is selected");
      return null;
    }
    //Store the layers which are selected
    var selectedLayers = []
    for (var i=1; i<=comp.numLayers; i++){
        if (comp.layer(i).selected) selectedLayers.push(i)
    }
  
    // add a temp null;
    var newNull = comp.layers.addNull();
    var newColorControl = newNull.property("ADBE Effect Parade").addProperty("ADBE Color Control");
    var theColorProp = newColorControl.property("ADBE Color Control-0001");
  
    // shy and turn eyeball off
    var origShyCondition = comp.hideShyLayers;
    if(origShyCondition == false) comp.hideShyLayers = true;
    newNull.shy = true;
    newNull.enabled = false;
  
    // set the value given by the function arguments
    theColorProp.setValue(startValue);
  
    // prepare to execute
    var editValueID = 2240
    theColorProp.selected = true;
    app.executeCommand(editValueID);
  
    // harvest the result
    var result = theColorProp.value;
  
    // remove the null
    if(newNull){
      newNull.remove();
    }
  
    // get shy condition back to original
    comp.hideShyLayers = origShyCondition;
  
    // restore Layer Selection
    for (var i=0; i<selectedLayers.length; i++){
      comp.layer(selectedLayers[i]).selected = true;
    }
    
    // if the user click cancel, the function will return the start value but as RGBA. In that case, return null
    var startValueInRgba = [startValue[0], startValue[1], startValue[2], 1];
    return (result.toString() == startValueInRgba.toString()) ? null : result;
}
Participant
April 7, 2021

It's me through another account because Adobe thinks I'm spamming.

Okay I just realised a possible workaround:

app.executeCommand(app.findMenuCommandId("Edit Value..."));

probably smarter to store the ID as a number to make sure it works in all languages of After-Effects, but the idea is to add a color control, target the color property and launch the "Edit Value" command in order to access the regular color picker, then probably harvest the color from the color control and get rid of it.

 

I'm going to give it a try and post the code later if it works.

Adobe please 🙃 with peace and love, make this built in.

Tomas Sinkunas
Legend
April 7, 2021

Yeap, that sounds like a reasonable workaround.

_SaCorrect answer
Participant
April 7, 2021
function GoodBoyNinjaColorPicker(startValue){
  // find the active comp
  var crntComp = app.project.activeItem;
  if (!crntComp || !(crntComp instanceof CompItem)) {
    alert("Please open a comp first");
    return [];
  }

  // add a temp null;
  var newNull = crntComp.layers.addNull();
  var newColorControl = newNull("ADBE Effect Parade").addProperty("ADBE Color Control");
  var theColorProp = newColorControl("ADBE Color Control-0001");

  // set the value given by the function arguments
  if (startValue && startValue.length == 3) {
    theColorProp.setValue(startValue);
  }

  // prepare to execute
  var editValueID = 2240 // or app.findMenuCommandId("Edit Value...");
  theColorProp.selected = true;
  app.executeCommand(editValueID);

  // harvest the result
  var result = theColorProp.value;

  // remove the null
  if (newNull) {
    newNull.remove();
  }

  return result;
}

// launch the true color picker with a white color
alert(GoodBoyNinjaColorPicker([1,1,1]));

 

This seem to do the trick. Could use some more error checking, also it takes an array of size 3 for the default value and returns an array of size 4 cause the harvested color has an alpha channel. If somebody wants to use it and make it feel even nicer you could make the new null a shy and turn on shy layers for the comp (but don't just turn it off later because the user could have it on to begin with, instead store the original state and revert to it).

 

Hope it helps someone.

Bye!

 

 

Tomas Sinkunas
Legend
April 7, 2021

The default $.colorPicker is actually a pita. However, there's a free script that you can use to invoke more dynamic ir ritcher color picker: https://github.com/smallpath/adobe-color-picker

 

At some point, I believe, @zlovatt was using above script as well.

Participant
April 7, 2021

I saw this before on github and I'm trying to avoid the complexity if integrating this 🙃

What do you think about the workaround I just posted in the comment below? Still didn't try it from start to finish but it does open the correct color picker so as long as it all works as expected it might be a good solution for me, and hopefully for more people in the future.

 

Thanks a bunch Tomas