UXP - Get user adjustments from displayed dialog?

In extendscript it is possible to return a descriptor and get values entered by the user. For this expendscript example, there is already a solid color layer in the document. This will open up the dialog for the user to change the colors and then return the RGB values the user selected in the dialog.

Is there a way to do this in UXP?

var redCurrent=128;
var greenCurrent=128;
var blueCurrent=128;

var desc  =  changeSolidColor(redCurrent,greenCurrent,blueCurrent);

var ToDesc = desc.getObjectValue(charIDToTypeID( "T   " ));
var list = ToDesc.getList(charIDToTypeID( "Clr " ));
var levelDesc = list.getObjectValue(0);
var redNew=Math.round(levelDesc.getDouble(charIDToTypeID( "Rd  " )));
var greenNew=Math.round(levelDesc.getDouble(charIDToTypeID( "Grn " )));
var blueNew=Math.round(levelDesc.getDouble(charIDToTypeID( "Bl  " )));

function changeSolidColor(red,green,blue){
var id30 = charIDToTypeID( "setd" );
    var desc7 = new ActionDescriptor();
    var id31 = charIDToTypeID( "null" );
        var ref2 = new ActionReference();
        var id32 = stringIDToTypeID( "contentLayer" );
        var id33 = charIDToTypeID( "Ordn" );
        var id34 = charIDToTypeID( "Trgt" );
        ref2.putEnumerated( id32, id33, id34 );
    desc7.putReference( id31, ref2 );
    var id35 = charIDToTypeID( "T   " );
        var desc8 = new ActionDescriptor();
        var id36 = charIDToTypeID( "Clr " );
            var desc9 = new ActionDescriptor();
            var id37 = charIDToTypeID( "Rd  " );
            desc9.putDouble( id37, red );
            var id38 = charIDToTypeID( "Grn " );
            desc9.putDouble( id38, green );
            var id39 = charIDToTypeID( "Bl  " );
            desc9.putDouble( id39, blue );
        var id40 = charIDToTypeID( "RGBC" );
        desc8.putObject( id36, id40, desc9 );
    var id41 = stringIDToTypeID( "solidColorLayer" );
    desc7.putObject( id35, id41, desc8 );
return userRGB = executeAction( id30, desc7, DialogModes.ALL );
}
1 Like

I’d assume that you could record the equivalent uxp code for the event and just add
_options": { "dialogOptions": "display" }
to the descriptor, but I haven’t tested it. (In the CEP code that’s the DialogModes.ALL part)

Apart from that, you can also just show a color picker at any time via:

const openPicker = {
    _target: { _ref: "application" },
    _obj: "showColorPicker",
    context,
    color,
  };
  const res = await photoshop.action.batchPlay([openPicker], {})
  const rgbFloat = res[0].RGBFloatColor

But that wouldn’t give you any live updates while changing the color, as the picker isn’t connected to the change solid color event. And be aware that the resulting color has decimals for r,g and b, so you might want to round each of the components.

1 Like

Here is one possible approach with UXP

Function callColors() will:
1- open PS ColorPicker with R=G=B=128
2- get the current selected layer colors (assuming it’s a Solid Color type)
3- store new rounded R; G; B values in a userColors array…

const batchPlay = require("photoshop").action.batchPlay;

async function callColors() {

  await batchPlay(
    [{
      "_obj": "set",
      "_target": [{
        "_ref": "contentLayer",
        "_enum": "ordinal",
        "_value": "targetEnum"
      }],
      "to": {
        "_obj": "solidColorLayer",
        "color": {
          "_obj": "RGBColor",
          "red": 128,
          "grain": 128,
          "blue": 128
        }
      },
      "_isCommand": true,
      "_options": {
        "dialogOptions": "display"
      }
    }], {
      "synchronousExecution": false,
      "modalBehavior": "fail"
    });

  let userColors = await testColors();

  console.log(userColors)
}

async function testColors() {
  var currentDocument = app.activeDocument
  var layers = currentDocument.activeLayers;
  var currentLayer = layers[0];

  const result = await batchPlay(
    [{
      "_obj": "get",
      "_target": [{
        "_ref": "layer",
        "_id": currentLayer._id
      }],
      "_options": {
        "dialogOptions": "dontDisplay"
      }
    }], {
      "synchronousExecution": false,
      "modalBehavior": "fail"
    });

  var userRed = Math.round(result[0].adjustment[0].color.red);
  var userGreen = Math.round(result[0].adjustment[0].color.grain);
  var userBlue = Math.round(result[0].adjustment[0].color.blue);
  var userColors = [userRed, userGreen, userBlue];
  return userColors;
}

Hope this helps !

Merry Xmas :christmas_tree: :smiley:

1 Like

Thank you Pierre and Simon!!! Merry Christmas and Happy New Year :slight_smile:

I just did a quick test and got both to work. I actually have uses for both examples because Simon’s uses the color picker without the solid color layer and Pierre’s uses the solid color layer. So depending on the situation, both have unique use cases.

For Simon’s examples, I have to remove context and color from the descriptor for it to pull up the color picker. This is the revised code.

const openPicker = {
    _target: { _ref: "application" },
    _obj: "showColorPicker"
  };
  const res = await require("photoshop").action.batchPlay([openPicker], {});
  const rgbFloat = res[0].RGBFloatColor;
  var userColors=[Math.round(rgbFloat.red),Math.round(rgbFloat.grain),Math.round(rgbFloat.blue)];
1 Like

Oh, maybe I should have explained those 2 keys…You can add a title for the color picker (context) and the color to start with:

const openPicker = {
  _target: { _ref: "application" },
  _obj: "showColorPicker",
  context: "Some title for the color picker...",
  color: {
    _obj: 'RGBColor',
    red: 0,
    green: 0,
    blue: 0,
  },
};
const res = await photoshop.action.batchPlay([openPicker], {})
const rgbFloat = res[0].RGBFloatColor
1 Like

Thanks. I figured there were suppose to be values there but wasn’t sure what it needed. So deleting them just went with defaults for the color and nothing for the title. The color key will be helpful for forcing the color starting point for sure.