• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
1

Photoshop 2015 artboards in scripting

Enthusiast ,
Jun 11, 2015 Jun 11, 2015

Copy link to clipboard

Copied

Anyone seen info / had a chance to test how artboards will workout in scripting? I guess data model could be pretty similar, i.e. an artboard is just new kind of group. The primary effect is in rendering / display, but probably most scripts will at least need an adjustment in logic (i.e. do you run through all art boards as one/separate or just the "active one".

Sneak Peek: Artboards in Photoshop CC - YouTube

TOPICS
Actions and scripting

Views

7.7K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe
Community Expert ,
Jun 11, 2015 Jun 11, 2015

Copy link to clipboard

Copied

Very broad questions for a feature that isn't even released yet.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 11, 2015 Jun 11, 2015

Copy link to clipboard

Copied

I think on the 16th Adobe is going to officially announce CC 2015.

The Artboards demo was not very impressive to me.  I would not need such a feature. I do not develop web pages or touch type apps.  The Artboard demo just look like a new type of Layer group that are call Artboards instead of Layer Group.  These seem to be spread out over a canvas that seem to automatically expand as you create new Artboards.  Artboards can be resized using preset sizes.

JJMack

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Jun 11, 2015 Jun 11, 2015

Copy link to clipboard

Copied

@Chuck: Trying to figure out if I should be excited of the possibilities or worried about how it'll break every script I have

Artboards seems pretty much an app designer thing, probably not so useful in web scale as it's hard to have multiple boards visible at reasonable zoom..

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 12, 2015 Jun 12, 2015

Copy link to clipboard

Copied

Matias, I would imagine they script like groups, as they seem to be just another type of container for layers, but that's just a guess. So I would imagine they will not break old scripts, other than I'm not sure how scripts that go through all the layers now will work. I guess it could be a problem if either you can't tell the difference between a group and an art board, or the old scripts need to be updated, because it doesn't know what to do with them. Looks like we will find out soon. Yes, they do seem to be just for designers, but maybe others can find uses for them. With the explosion of mobile devices, designers do need a way to be able to layout multiple designs easily. Having to work with multiple documents and attempting to tile all the windows could be a real pain.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Jun 16, 2015 Jun 16, 2015

Copy link to clipboard

Copied

That happened quicker than I thought

One potentially big thing thing if you handle whole documents is that with Artboards the canvas size becomes virtual/fluid. I.e. it's still just one doc with one canvas and the size of the canvas being about the bounding box of all artboards. Each Artboard has it's bounds (just like it was a group in a big empty canvas) that also acts as mask. Creating/moving Artboards will automatically extend the canvas size. So if you have two 1024x768 Artboards horizontally with 200px in between, you will have about 3500x1000px canvas (there is some extra).

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 16, 2015 Jun 16, 2015

Copy link to clipboard

Copied

Yes, that could be an issue. I think a whole new way of dealing with artboards is going to be required, plus a check to see if a document has artboards so you don't assume that the doc dimensions are static.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Jun 16, 2015 Jun 16, 2015

Copy link to clipboard

Copied

My scripts usually start by duplicating the doc so to not change the original. I should be able to put the logic of if-artboard-or-doc there. It could also be a workaround for hidden "it's a document"-assumptions, i.e. start by duplicating the artboard to a doc.

Another note is that current ESTK will work with artboards but you can't tell them apart from layerSets. Also you have no access to artboard size since layerSet.bounds is the normal content dimensions. So there needs to be an SDK update from Adobe to do Javascript. Interestingly even old Generator development environment works out of the box and gives the artboard bounds.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 16, 2015 Jun 16, 2015

Copy link to clipboard

Copied

I haven't looked for the new SDK yet, but if it isn't out, it should be soon. There are a lot of new features to deal with artboards. From a description that Tim Wright gave, it looks like you can turn off the artboard features temporarily, which I'm guessing will help with the issue of doc size. Here are a few things Tim said about the new feature:

Yes, Artboards mostly work like layer groups, as far as moving, renaming, etc.  You can do almost anything to an Artboard that you can do to a layer group, except nest them within another artboard/group.  There are some new scriptable commands to modify the Artboard rectangle (it’s like an additional mask on the artboard layer group), to convert layer groups to artboards, and vice versa.  There’s also a way to temporarily turn off the artboard specific behaviors in a script: the automatic nesting overlapping layers inside the artboard group, and the auto-expand/infinite canvas feel.  Sometimes you might want to save the special Artboard behavior till the end to make the scripting logic easier/faster, or you have a script that already works with groups that you want to use.

The artboard layer groups have hidden "section bounder" layers, too, that demarcate the end of the group.  You can use the same scripting APIs used for layer groups to navigate artboard groups. There’s also a new property on the document that gives the layer index ranges of all the artboards in a single array. I think it’s artboards:{list:[{top,bottom}, ... ]}. It should be mentioned in the new SDK somewhere.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Employee ,
Jun 16, 2015 Jun 16, 2015

Copy link to clipboard

Copied

Here's some really raw scripting info, but it might help get you started if you're already familiar with scripting. For example usage it may help to look at the ExtendScript source for Artboards to PDF (Presets/Scripts/ArtBoards To PDF.jsx). You need to use the long form to access the properties (not the "dot" notation) it will look something like:

var theRef = new ActionReference();
theRef.putProperty(classProperty, theProp);
theRef.putEnumerated(theClass, typeOrdinal, enumTarget);

getDescriptor.putReference(propNull,theRef);

var desc = executeAction( charIDToTypeID( "getd" ), getDescriptor, DialogModes.NO );

//Layer properties:

artboardEnabled (bool) //is the layer an artboard (set top) layer

artboard (object)

     artboardRect (object)  //bounds of artboard

          top (float)

          left (float)

          bottom (float)

          right (float)

//Doc properties

artboards (object)

     list (list)  //list of artboard layer index ranges

          top  //the artboard

          bottom //the bottommost member

     origin (object) //amount doc coordinates have shifted due to auto-expand (in the upper/left directions)

          horizontal (float)

          vertical (float)

     canvasColorMode (enum, type TypeCanvasColorType)

          defaultGray/black/darkGray/mediumGray/lightGray/custom    

     canvasColor  //custom canvas color

          red (float 0-255.)

          green (float)

          blue  (float)

     //use these 3 with caution: these should be true normally (also accessible via "gear" icon in Artboard toolbar)

     autoExpandEnabled (bool)  //layers/artboards expand doc

     autoNestEnabled (bool) //layers auto nest into artboards when they overlap

     autoPositionEnabled (bool)  //layers re-position to match prior container

//Additional commands:

artboardFromLayerGroupEvent

     artboard (object, same format as layer property)

editArtboardEvent

     artboard (object, same format as layer property)

     changeSizes (optional integer: eChangeRectangles=0, eChangeSizes=1, eForcePortrait=2, eForceLandscape=3)

     autoExpandEnabled (optional bool)

     autoNestEnabled (optional bool)

     autoPositionEnabled  (optional bool)

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 16, 2015 Jun 16, 2015

Copy link to clipboard

Copied

Thanks, Tim. Is the new SDK out yet?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Employee ,
Jun 16, 2015 Jun 16, 2015

Copy link to clipboard

Copied

Not yet, but it usually takes a little while after the release.  It should show up here when it's ready:

Adobe Photoshop SDK | Adobe Developer Connection

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 16, 2015 Jun 16, 2015

Copy link to clipboard

Copied

Thanks, Tim.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jun 17, 2015 Jun 17, 2015

Copy link to clipboard

Copied

Tim or Chuck, I haven't figured out how to access the document level array of all artboards that you mention. Any cues on how to do that?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 17, 2015 Jun 17, 2015

Copy link to clipboard

Copied

I haven't tried that yet.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Jun 17, 2015 Jun 17, 2015

Copy link to clipboard

Copied

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Jun 17, 2015 Jun 17, 2015

Copy link to clipboard

Copied

In DOM artBoards are just the top level groups in document.layerSets. What you really need is

a) method of checking if the layerSet is an artBoard or not

b) method of getting artBoard rectangle so you can adjust coordinates (and maybe adjusting it). So the layerSet bounds/coordinates will in full document coordinates and if you want/need to use the artBoard "as a doc" with top left in (0,0) then you need to do adjustments 

But for that we'll need to wait I guess..

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jun 18, 2015 Jun 18, 2015

Copy link to clipboard

Copied

You can do this:

            // check if active layer is an artboard
            var ref = new ActionReference();
            ref.putEnumerated( charIDToTypeID( "Lyr " ), charIDToTypeID( "Ordn" ), charIDToTypeID( "Trgt" ) );
            var isArtboardLayer = executeActionGet(ref).getBoolean(stringIDToTypeID("artboardEnabled"));

            // get artboard dimensions
            var artBoardRect = executeActionGet(ref).getObjectValue(stringIDToTypeID("artboard")).getObjectValue(stringIDToTypeID("artboardRect"));
            var artBoardRectWidth = new UnitValue (artBoardRect.getDouble(stringIDToTypeID("right")) - artBoardRect.getDouble(stringIDToTypeID("left")), "px");
            var artBoardRectHeight = new UnitValue (artBoardRect.getDouble(stringIDToTypeID("bottom")) - artBoardRect.getDouble(stringIDToTypeID("top")), "px");

But I'm still struggling for a way to read the current value of the "autoExpandEnabled" setting... anyone?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Jun 18, 2015 Jun 18, 2015

Copy link to clipboard

Copied

function cTID(s) {return app.charIDToTypeID(s);}

function sTID(s) {return app.stringIDToTypeID(s);}

function newArtboard(_name, _w, _h) {

  var desc6 = new ActionDescriptor();

  var ref1 = new ActionReference();

  ref1.putClass(sTID('artboardSection'));

  desc6.putReference(cTID('null'), ref1);

  var desc7 = new ActionDescriptor();

  desc7.putString(cTID('Nm '), _name);

  desc6.putObject(cTID('Usng'), sTID('artboardSection'), desc7);

  var desc8 = new ActionDescriptor();

  desc8.putDouble(cTID('Top '), 0.000000);

  desc8.putDouble(cTID('Left'), 0.000000);

  desc8.putDouble(cTID('Btom'), _h);

  desc8.putDouble(cTID('Rght'), _w);

  desc6.putObject(sTID('artboardRect'), sTID('classFloatRect'), desc8);

  executeAction(cTID('Mk '), desc6, DialogModes.NO);

}

function main() {

  var fileList = app.openDialog("Select your files"),

  delta = 0,

  currentDocWidth = 0;

  if (fileList != null && fileList != "") {

  var doc = app.documents.add(400, 400, 72, "File1");

  for (var i = 0; i < fileList.length; i++) {

  app.open(fileList);

  currentDocWidth = app.activeDocument.width.value + 20;

  app.runMenuItem(sTID('selectAllLayers'));

  newArtboard(app.activeDocument.name, app.activeDocument.width.value, app.activeDocument.height.value);

  app.activeDocument.activeLayer.duplicate(doc, ElementPlacement.INSIDE);

  app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);

  if (i > 0) {

  app.activeDocument.activeLayer.translate(delta, 0);

  }

  delta = delta + currentDocWidth;

  }

  doc.crop([0, 0, app.activeDocument.width, app.activeDocument.height], 0, delta);

  app.runMenuItem(charIDToTypeID("FtOn"));

  alert('Done!');

  }

}

main();

props to nvkzNemo

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Employee ,
Jun 18, 2015 Jun 18, 2015

Copy link to clipboard

Copied

As a general tip, Install the Script Listener plugin (optional down-loadable plugin) to discover ExtendScript for any recordable action.

I'm including a sample script to do a bunch of things with Artboards. This shows how to create Artboards via a script in a few ways, and also how read existing artboard attributes.   This should help with the doc-wide "artboards" property (list of all artboard indeces, auto-expand enabled) as well as the layer-specific "artboards" property that holds the rectangle for the layer's artboard.

Caveat emptor, etc. I've only briefly tested this, so it's up to you to shake out any bugs in your own coding situations.

// =======================================================

// Copyright 2015.  Adobe Systems, Incorporated.  All rights reserved.

// Demonstrates basic scripting of artboards

// =======================================================

var classProperty = charIDToTypeID('Prpr');

var typeOrdinal = charIDToTypeID('Ordn');

var enumTarget = charIDToTypeID('Trgt');

var classDocument = charIDToTypeID('Dcmn');

var classLayer = charIDToTypeID('Lyr ');

var idnull = stringIDToTypeID( "null" );

// =======================================================

function DoAction(inActionName, inDescriptor) {

  return executeAction( stringIDToTypeID(inActionName), inDescriptor, DialogModes.NO );

  }

// =======================================================

function MakeDocTargetRef() {

  var ref12 = new ActionReference();

  ref12.putEnumerated( classDocument, typeOrdinal, enumTarget );

  return ref12;

  }

// =======================================================

function TargetLayers() {

  var ref12 = new ActionReference();

  ref12.putEnumerated( classLayer, typeOrdinal, enumTarget );

  return ref12;

  }

// =======================================================

function IndexedLayer(inIndex) {

  var ref12 = new ActionReference();

  ref12.putIndex( classLayer, inIndex );

  return ref12;

  }

// =======================================================

var idprevious= stringIDToTypeID( "previous" );

function PreviousLayer() {

  var ref12 = new ActionReference();

  ref12.putEnumerated( classLayer, idnull, idprevious );

  return ref12;

  }

// =======================================================

function Layer() {

  var ref12 = new ActionReference();

  ref12.putClass( classLayer );

  return ref12;

  }

// =======================================================

function IndexedLayers(inIndeces) {

  var ref12 = new ActionReference();

  for (var ll = 0; ll < inIndeces.length; ll++)

  {

  ref12.putIndex( classLayer, inIndeces[ll] );

  }

  return ref12;

  }

// =======================================================

function NamedLayer(inName) {

  var ref16 = new ActionReference();

  ref16.putName( classLayer,inName );

  return ref16;

  }

// =======================================================

function TargetLayerRef(inProp) {

  var theRef = new ActionReference();

  theRef.putProperty(classProperty, inProp);

  theRef.putEnumerated(classLayer, typeOrdinal, enumTarget);

  return theRef;

  }

// =======================================================

function IndexedLayerRef(inIndex,inProp) {

  var theRef = new ActionReference();

  theRef.putProperty(classProperty, inProp);

  theRef.putIndex(classLayer, inIndex+1); //putIndex uses 1-based index

  return theRef;

  }

// =======================================================

var idartboards = stringIDToTypeID( "artboards" );

var idorigin = stringIDToTypeID( "origin" );

var idlist = stringIDToTypeID( "list" );

var idtop = stringIDToTypeID( "top" );

var idbottom = stringIDToTypeID( "bottom" );

var idcanvasColor = stringIDToTypeID( "canvasColor" );

var idcanvasColorMode = stringIDToTypeID( "canvasColorMode" );

var idautoNestEnabled = stringIDToTypeID( "autoNestEnabled" );

var idautoExpandEnabled = stringIDToTypeID( "autoExpandEnabled" );

var idred = charIDToTypeID( 'Rd  ' );

var idgreen = charIDToTypeID( 'Grn ' );

var idblue = charIDToTypeID( 'Bl  ' );

var propArtboards = stringIDToTypeID("artboards");

var actionGet = charIDToTypeID( "getd" );

function TargetArtboardInfo() {

  var theRef = new ActionReference();

  theRef.putProperty(classProperty, propArtboards);

  theRef.putEnumerated(classDocument, typeOrdinal, enumTarget);

  var getDescriptor = new ActionDescriptor();

  getDescriptor.putReference(idnull,theRef);

  var abDesc = executeAction( actionGet, getDescriptor, DialogModes.NO ).getObjectValue(idartboards);

  var abOrigin = abDesc.getObjectValue(idorigin);

  var abCanvasColor = abDesc.getObjectValue(idcanvasColor);

  var abList = [];

  var abDescList = abDesc.getList( stringIDToTypeID( 'list' ));

  var abCount = abDescList.count;

  for(var cc=0;cc<abCount;++cc) {

  var abObj = abDescList.getObjectValue( cc );

  var abTopIndex = abObj.getInteger(idtop);

  var abBottomIndex = abObj.getInteger(idbottom);

  abList.push( {top:abTopIndex, bottom:abBottomIndex, rect:IndexedArtboardRect(abTopIndex), name:IndexedArtboardName(abTopIndex)});

  }

  return {origin:{x:abOrigin.getInteger(idhorizontal), y:abOrigin.getInteger(idvertical)},

  list:abList,

  autoExpandEnabled:abDesc.getBoolean(idautoExpandEnabled),

  autoNestEnabled:abDesc.getBoolean(idautoNestEnabled),

  canvasColorMode:typeIDToStringID(abDesc.getEnumerationValue(idcanvasColorMode)),

  canvasCustomColor:{red:abCanvasColor.getInteger(idred), green:abCanvasColor.getInteger(idgreen), blue:abCanvasColor.getInteger(idblue)}

  };

  }

// =======================================================

var idartboard = stringIDToTypeID( "artboard" );

var idartboardRect = stringIDToTypeID( "artboardRect" );

function RefArtboardRect(theRef) {

  var getDescriptor = new ActionDescriptor();

  getDescriptor.putReference(idnull,theRef);

  var artboardRect = executeAction( actionGet, getDescriptor, DialogModes.NO )

  .getObjectValue(idartboard).getObjectValue(idartboardRect);

  return {top: artboardRect.getInteger(idtop),

  left: artboardRect.getInteger(idleft),

  bottom: artboardRect.getInteger(idbottom),

  right: artboardRect.getInteger(idright)};

  }

// =======================================================

var propArtboardEnabled = stringIDToTypeID( "artboardEnabled" );

function TargetIsArtboard() {

  var getDescriptor = new ActionDescriptor();

  getDescriptor.putReference(idnull,TargetLayerRef(propArtboardEnabled));

  return executeAction( actionGet, getDescriptor, DialogModes.NO ).getBoolean(propArtboardEnabled);

}

// =======================================================

var propArtboard = stringIDToTypeID("artboard");

function TargetArtboardRect() {

  return RefArtboardRect(TargetLayerRef(propArtboard));

  }

// =======================================================

function IndexedArtboardRect(inIndex) {

  return RefArtboardRect(IndexedLayerRef(inIndex,propArtboard));

  }

// =======================================================

var propName = stringIDToTypeID( "name" );

function IndexedArtboardName(inIndex) {

  var getDescriptor = new ActionDescriptor();

  getDescriptor.putReference(idnull,IndexedLayerRef(inIndex,propName));

  return executeAction( actionGet, getDescriptor, DialogModes.NO ).getString(propName);

  }

// =======================================================

var propRulerOriginH = stringIDToTypeID( "rulerOriginH" );

var propRulerOriginV = stringIDToTypeID( "rulerOriginV" );

function TargetRulerOrigin() {

  var theRef = new ActionReference();

  theRef.putProperty(classProperty, propRulerOriginH);

  theRef.putProperty(classProperty, propRulerOriginV);

  theRef.putEnumerated(classDocument, typeOrdinal, enumTarget);

  var getDescriptor = new ActionDescriptor();

  getDescriptor.putReference(idnull,theRef);

  var rulerOrigin = executeAction( actionGet, getDescriptor, DialogModes.NO );

  return {x:rulerOrigin.getInteger(propRulerOriginH) / 65536,

  y:rulerOrigin.getInteger(propRulerOriginH) / 65536};

  }

// =======================================================

var idhorizontal = stringIDToTypeID( "horizontal" );

var idvertical = stringIDToTypeID( "vertical" );

var iddistanceUnit = stringIDToTypeID( "distanceUnit" );

function MakePoint(inX, inY) {

    var point = new ActionDescriptor();

    point.putUnitDouble( idhorizontal, idpixelsUnit, inX );

    point.putUnitDouble( idvertical, idpixelsUnit, inY );

    return point;

  }

// =======================================================

var idred = stringIDToTypeID( "red" );

var idgreen = stringIDToTypeID( "green" );

var idblue = stringIDToTypeID( "blue" );

function MakeRGBColor(inR, inG, inB) {

  var color = new ActionDescriptor();

  color.putDouble( idred, inR );

  color.putDouble( idgreen, inG );

  color.putDouble( idblue, inB );

  return color;

  }

// =======================================================

var idfill = stringIDToTypeID( "fill" );

var idtransparency = stringIDToTypeID( "transparency" );

var idname = stringIDToTypeID( "name" );

var idwidth = stringIDToTypeID( "width" );

var idheight = stringIDToTypeID( "height" );

var idRGBColorMode = stringIDToTypeID( "RGBColorMode" );

var idmode = stringIDToTypeID( "mode" );

var idresolution = stringIDToTypeID( "resolution" );

var iddepth = stringIDToTypeID( "depth" );

var idnew = stringIDToTypeID( "new" );

var iddocument = stringIDToTypeID( "document" );

function MakeDocument(inName, inWidth, inHeight) {

  var desc3 = new ActionDescriptor();

  var desc4 = new ActionDescriptor();

  desc4.putString( idname, inName );

  desc4.putEnumerated( idfill, idnull, idtransparency );

    desc4.putUnitDouble( idwidth, idpixelsUnit, inWidth );

    desc4.putUnitDouble( idheight, idpixelsUnit, inHeight );

    desc4.putUnitDouble( idresolution, idpixelsUnit, 72.0 );

    desc4.putInteger( iddepth, 8 );

    desc4.putClass( idmode, idRGBColorMode );

  desc3.putObject( idnew, iddocument, desc4 );

  DoAction( "make", desc3 );

  }

// =======================================================

var idcontentLayer = stringIDToTypeID( "contentLayer" );

var idRGBColor = stringIDToTypeID( "RGBColor" );

var idsolidColorLayer = stringIDToTypeID( "solidColorLayer" );

var idshape = stringIDToTypeID( "shape" );

var idtop = stringIDToTypeID( "top" );

var idleft = stringIDToTypeID( "left" );

var idright = stringIDToTypeID( "right" );

var idbottom = stringIDToTypeID( "bottom" );

var idrectangle = stringIDToTypeID( "rectangle" );

var idunitValueQuadVersion = stringIDToTypeID( "unitValueQuadVersion" );

var idpixelsUnit = stringIDToTypeID( "pixelsUnit" );

var idcolor = stringIDToTypeID( "color" );

var idtype = stringIDToTypeID( "type" );

var idusing = stringIDToTypeID( "using" );

function MakeRectangleShape(inTop,inLeft,inBottom,inRight) {

    var rect = new ActionDescriptor();

    rect.putInteger(idunitValueQuadVersion, 1)

    rect.putUnitDouble( idtop, idpixelsUnit, inTop );

    rect.putUnitDouble( idleft, idpixelsUnit, inLeft );

    rect.putUnitDouble( idbottom, idpixelsUnit, inBottom );

    rect.putUnitDouble( idright, idpixelsUnit, inRight );

    return rect;

  }

// =======================================================

function MakeRectangleLayerAt(inTop, inLeft, inBottom, inRight, inRGBColor) {

  var desc6 = new ActionDescriptor();

  var ref2 = new ActionReference();

  ref2.putClass( idcontentLayer );

  desc6.putReference( idnull, ref2 );

  var desc7 = new ActionDescriptor();

     var desc8 = new ActionDescriptor();

     desc8.putObject( idcolor, idRGBColor, inRGBColor  );

  desc7.putObject( idtype, idsolidColorLayer, desc8 );

  desc7.putObject( idshape, idrectangle, MakeRectangleShape(inTop,inLeft,inBottom,inRight) );

  desc6.putObject( idusing, idcontentLayer, desc7 );

  DoAction( "make", desc6 );

  }

// =======================================================

var idto = stringIDToTypeID( "to" );

var idoffset = stringIDToTypeID( "offset" );

function DuplicateLayerTo(inLayerRef, inOffset) {

  var desc63 = new ActionDescriptor();

  desc63.putReference( idnull, inLayerRef );

  desc63.putObject( idto, idoffset, inOffset );

  DoAction( "copyEvent", desc63 );

  }

// =======================================================

var idselectionModifier = stringIDToTypeID( "selectionModifier" );

var idselectionModifierType = stringIDToTypeID( "selectionModifierType" );

var idaddToSelectionContinuous = stringIDToTypeID( "addToSelectionContinuous" );

function AddToSelection(inLayerRef) {

  var desc74 = new ActionDescriptor();

  desc74.putReference( idnull, inLayerRef );

  desc74.putEnumerated( idselectionModifier, idselectionModifierType, idaddToSelectionContinuous );

  DoAction( "select", desc74 );

  }

// =======================================================

var classArtboardSection = stringIDToTypeID( "artboardSection" );

var idfrom = stringIDToTypeID( "from" );

function MakeArtboardFromSelection(inLayerRef) {

  var desc = new ActionDescriptor();

  var ref = new ActionReference();

  ref.putClass( classArtboardSection );

  desc.putReference( idnull, ref );

  desc.putReference( idfrom, inLayerRef );

  //desc.putString( idname, inName );

  DoAction( "make", desc  );

  }

// =======================================================

var classLayerSection = stringIDToTypeID( "layerSection" );

function MakeLayerGroup() {

    var desc = new ActionDescriptor();

    var ref = new ActionReference();

    ref.putClass( classLayerSection );

    desc.putReference( idnull, ref );

  DoAction( "make", desc  );

  }

// =======================================================

function RectToDesc(inRect) {

  var rect = new ActionDescriptor();

  rect.putDouble( idtop, inRect.top );

  rect.putDouble( idleft, inRect.left );

  rect.putDouble( idright, inRect.right );

  rect.putDouble( idbottom, inRect.bottom );

  return rect;

}

// =======================================================

var classFloatRect = stringIDToTypeID( "classFloatRect" );

function MakeArtboardFromLayerGroup(inLayerRef, inRect) {

  var desc = new ActionDescriptor();

  desc.putReference( idnull, inLayerRef );

  var abDesc = new ActionDescriptor();

  abDesc.putObject( idartboardRect, classFloatRect, RectToDesc(inRect) );

  desc.putObject( idartboard, idartboard, abDesc );

  DoAction( "artboardFromLayerGroupEvent", desc  );

  }

// =======================================================

function MakeArtboard(inLayerRef, inRect) {

  var ref = new ActionReference();

  ref.putClass( classArtboardSection );

    var desc = new ActionDescriptor();

    desc.putReference( idnull, ref );

    desc.putObject( idartboardRect, classFloatRect, RectToDesc(inRect) );

  DoAction( "make", desc  );

}

// =======================================================

function EditArtboard(inLayerRef, inRect) {

  var desc = new ActionDescriptor();

  desc.putReference( idnull, inLayerRef );

  var abDesc = new ActionDescriptor();

  abDesc.putObject( idartboardRect, classFloatRect, RectToDesc(inRect) );

  desc.putObject( idartboard, idartboard, abDesc );

  DoAction( "editArtboardEvent", desc  );

}

// =======================================================

function RectToString(inRect) {

  return "" + inRect.top + ","  + inRect.left + ","  + inRect.bottom + "," + inRect.right;

  }

// =======================================================

function PointToString(inPt) {

  return "" + inPt.x + ","  + inPt.y;

  }

// =======================================================

function RGBToString(inRGB) {

  return "" + inRGB.red + ","  + inRGB.green + ","  + inRGB.blue;

  }

// =======================================================

function ABListToString(inList) {

  var str = "";

  for (var aa = 0; aa < inList.length; ++aa) {

  str += "   top:" + inList[aa].top +

  ", bottom:" + inList[aa].bottom +

  ", rect:" + RectToString(inList[aa].rect) +

  ", name:" + inList[aa].name + "\n";

  }

  return str;

  }

// =======================================================

// Display artboard rectangle of selected artboard.

function DisplayTargetArtboard() {

  if (TargetIsArtboard()) {

  var artboardRect = TargetArtboardRect();

  alert("Artboard: " + RectToString(artboardRect) );

  }

}

// =======================================================

// Display info about all artboard/artboard properties of active document.

function DisplayTargetArtboards() {

  var abInfo = TargetArtboardInfo();

  var rulerOrigin = TargetRulerOrigin();

  alert("Artboards\n" +

   "Artboards:\n" + ABListToString(abInfo.list)  + "\n" +

   "Artboard Origin: " + PointToString(abInfo.origin) + "\n" +

   "Auto Expand Enabled: " + abInfo.autoExpandEnabled + "\n" +

   "Auto Nest Enabled: " + abInfo.autoNestEnabled + "\n" +

   "Canvas Mode: " + abInfo.canvasColorMode + "\n" +

   (abInfo.canvasColorMode == 'custom' ? ("Canvas Custom Color: " + RGBToString(abInfo.canvasCustomColor) + "\n") : "") +

   "Ruler Origin: " + PointToString(rulerOrigin)

  );

}

// =======================================================

var abSpaceX = 1000;

var abSpaceY = 1000;

var abRows = 1;

var abCols = 3;

var rectX = 500;

var rectY = 500;

var rectWidth = 500;

var rectHeight = 500;

var abWidth = 512;

var abHeight = 512;

var placedX = 750; //center pos

var placedY = 750; //center pos

var dupOffsetX = 50;

var dupOffsetY = 50;

var abOriginX = 0;

var abOriginY = 0;

var createArtboardDoc = true;

if (createArtboardDoc) {

  // new document.

  MakeDocument("Artboard Sample", 2048, 2048);

  // create some artboards

  for (var rr = 0; rr < abRows; rr++) {

  for (var cc = 0; cc < abCols; cc++) {

  var posX = cc*abSpaceX;

  var posY = rr*abSpaceY;

  var rectPosX =  rectX + posX;

  var rectPosY = rectY + posY;

  var centerX =   (activeDocument.width/2);

  var centerY = (activeDocument.height/2);

  var placedPosX =   (placedX + posX) - activeDocument.width/2;

  var placedPosY = (placedY + posY) - activeDocument.height/2;

  var rectColor = MakeRGBColor((rr*cc*255)/(abRows*abCols),(rr*255)/abRows,(cc*255)/abCols);

  //create two rectangle shape layers, and put them into a new artboard.

  MakeRectangleLayerAt(rectPosY, rectPosX, rectPosY + rectHeight, rectPosX + rectWidth, rectColor);

  DuplicateLayerTo(TargetLayers(), MakePoint(dupOffsetX, dupOffsetY));

  AddToSelection( PreviousLayer() );

  MakeArtboardFromSelection(TargetLayers());

  DisplayTargetArtboard();

  }

  }

  //create a normal layer group, then convert it into an artboard with specified rectangle

  MakeLayerGroup();

  MakeArtboardFromLayerGroup(TargetLayers(), {top:2048,left:2048,bottom:2148,right:2148});

  DisplayTargetArtboard();

  //create new artboard with specified rectangle

  MakeArtboard(TargetLayers(), {top:2048,left:2248,bottom:2148,right:2348});

  DisplayTargetArtboard();

  //change artboard rect of selection

  EditArtboard(TargetLayers(), {top:2048,left:2348,bottom:2148,right:2448});

  DisplayTargetArtboard();

}

//show doc-wide artboard info

DisplayTargetArtboards();

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Explorer ,
Jun 18, 2015 Jun 18, 2015

Copy link to clipboard

Copied

Thanks Tim. That's very helpful!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jul 10, 2015 Jul 10, 2015

Copy link to clipboard

Copied

I still struggle with this type of code (I think I've seen it called Action Manager code). I've spent two evenings trying to modify this to get me the bounds and offset of the only the artboard that contains the currently selected layer(s). From poking through the script above, I can get the active artboard IF an artboard is selected, however if a layer is selected it does nothing. I can also get it to get a list of artboards and their info. Again this is all already in the script. What I can't figure out how to do is get the parent artboard for a selected layer, or alternatively, figure out which artboard in the list has the selected layer in it.

Any suggestions?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Employee ,
Jul 13, 2015 Jul 13, 2015

Copy link to clipboard

Copied

Here's some code to get the selected layers in a document: Photoshop: Get selected layers with Photoshop CC scripting API

Once you have the indeces of the selected layers, it's just a matter of finding them in the Artboard list.

So something like this:

function GetArtboardForLayerIndex(inArtboardList,inLayerIndex) {

     var parentArtboardIndex = -1;

     for (var aa = 0; aa < inArtboardList.length; ++aa) {

          if (inArtboardList[aa].bottom <= inLayerIndex && inArtboardList[aa].top >= inLayerIndex) {

               return inArtboardList[aa].top;

          }

     }

     return parentArtboardIndex;

}

inArtboardList uses the object format for the artboard list in my previous example. It returns -1 if the layer index is not in an artboard.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Enthusiast ,
Oct 14, 2015 Oct 14, 2015

Copy link to clipboard

Copied

BTW, how about an SDK update (or a timeframe for one) to treat artboards as first class citizens?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 04, 2016 Feb 04, 2016

Copy link to clipboard

Copied

Hi there.

Just wondering if there was any news here ?

I tried the https://github.com/antoniocosta/photoshopscripts/blob/master/Layer%20Comps%20To%20Artboard%20Files.j... method, but it fails here, so i'm wondering if this SDK problem is involved.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines