10 Replies Latest reply on Jun 20, 2010 8:00 AM by Muppet Mark-QAl63s

    Connect-the-dots in photoshop




      I want the ability to make a connect-the-dots game in photoshop, with the following functionality:


      1) you click somewhere on the canvas, and it draws a dot, next to the dot it draws the number 1.

      2) next time to click on the canvas, it draws another dot, and next to that dot draws the number 2.

      3) the next time you click, it draws another dot with 3, then 4, etc. etc.


      My question is: is this possible to do using photoshop scripting? or will I have to write a plugin? Any leads where I might start looking for info about implementing this functionality?


      Also, if anyone can tell me of another plugin or program that does this already, I would appreciate to hear about it (it would save me doing it myself!).


      One note - the solution must be able to deal with very large files and handle thousands of dots (I've come across a couple of websites which make connect the dots but they can't handle large files).


      Thanks :-)

        • 1. Re: Connect-the-dots in photoshop
          c.pfaffenbichler Level 9

          Sounds interesting.


          But a change in the procedure might make it more easy to Script:

          Dropping interactivity and instead creating a common path, the pathPoints of which the Script then uses to place circles plus numbers afterwards.


          I may have misunderstood your intention, though.

          • 2. Re: Connect-the-dots in photoshop
            c.pfaffenbichler Level 9

            Well, on the basis of a pathItem it works, but I haven’t tested it for very large numbers of points yet; if your heart is set on click/creating the dots and numbers that might also be possible, but is probably much more complicated.

            • 3. Re: Connect-the-dots in photoshop
              Muppet Mark-QAl63s Level 4

              While taking a very brief look for the first time at CS5 there was a feature that was new 'well to me it was' up in the menu bar near help 'Analyze' maybe? and there was a counter thingy in that where you could put auto numbered markers on an image? Have you looked at this? Sorry no idea at this time if scriptlistener or the DOM has access to this others will know that already Im sure…

              • 4. Re: Connect-the-dots in photoshop
                jayarg Level 1

                Hi c.pfaffenbichler, that solution sounds good. Would you mind posting the

                script you wrote? or just giving a step by step guide to how to reproduce




                • 5. Re: Connect-the-dots in photoshop
                  c.pfaffenbichler Level 9

                  Well, I haven’t bothered with a dialog to select the path yet, so currently the Script just uses the topmost path (pathItems[0]).

                  The dot being a Smart Object should allow for easy changes of that, but changing the type would be a bit more difficult, so best to define it the way you want it in the Script itself.

                  Furthermore the numbers are dual (like »1_1« for example) for cases where more than one subPathItem exists.

                  Anyway, if you want to give it a try, here is the current state:


                  // create circle-smart objects and numbers for a connect-the-dots of the topmost path;

                  // for mac and cs4;

                  // 2010, pfaffenbichler; use it at your own risk;

                  #target photoshop

                  if (app.documents.length > 0 && app.activeDocument.pathItems.length != 0) {

                  // set to 72dpi and pixels;

                  var originalRulerUnits = preferences.rulerUnits;

                  preferences.rulerUnits = Units.PIXELS;

                  var myDocument = app.activeDocument;

                  var originalResolution = myDocument.resolution;

                  myDocument.resizeImage(undefined, undefined, 72, ResampleMethod.NONE);

                  // get path info;

                  var myPathInfo = extractSubPathInfo(myDocument.pathItems[0]);

                  // create a smart object;

                  theArray = [[[[0,-3],[1.66,-3],[-1.66,-3],"SMOOTH"],



                  [[-3,0],[-3,-1.66],[-3,1.66],"SMOOTH"], true]];

                  var aPath = createPath10 (theArray, "circle");


                  makeFillLayer ("circle", 0, 0, 0);

                  // convert to smart object ;

                  var id557 = charIDToTypeID( "slct" );

                  var desc108 = new ActionDescriptor();

                  var id558 = charIDToTypeID( "null" );

                  var ref77 = new ActionReference();

                  var id559 = charIDToTypeID( "Mn  " );

                  var id560 = charIDToTypeID( "MnIt" );

                  var id561 = stringIDToTypeID( "newPlacedLayer" );

                  ref77.putEnumerated( id559, id560, id561 );

                  desc108.putReference( id558, ref77 );

                  executeAction( id557, desc108, DialogModes.NO );

                  var theSO = myDocument.activeLayer;

                  // remove path;


                  // create a set;

                  var theSet = myDocument.layerSets.add();

                  theSet.name = "connectTheDots";

                  // work through the path points;

                  for (var m = 0; m < myPathInfo.length; m++) {

                  var subPath = myPathInfo[m].entireSubPath;

                  for (var n = 0; n < subPath.length; n++) {

                  var theArray = subPath[n].anchor;

                  // make circle;

                  var theCircle = theSO.duplicate(theSet, ElementPlacement.PLACEATBEGINNING);

                  myDocument.activeLayer = theCircle;

                  theCircle.translate(theArray[0], theArray[1]);

                  theCircle.name = (m+1)+"_"+(n+1)+"_circle";

                  // make texts;

                  makeNumber (theSet, (m+1)+"_"+(n+1), theArray[0], theArray[1] - 12)



                  theSO.visible = false;

                  // reset image size;

                  myDocument.resizeImage(undefined, undefined, originalResolution, ResampleMethod.NONE);

                  preferences.rulerUnits = originalRulerUnits;





                  ////// based on michael l hale’s code //////

                  function extractSubPathInfo(pathObj){

                  var pathArray = new Array();

                  var pl = pathObj.subPathItems.length;

                  for(var s=0;s<pl;s++){

                  var pArray = new Array();

                  for(var i=0;i<pathObj.subPathItems[s].pathPoints.length;i++){

                  pArray[i] = new PathPointInfo;

                  pArray[i].kind = pathObj.subPathItems[s].pathPoints[i].kind;

                  pArray[i].anchor = pathObj.subPathItems[s].pathPoints[i].anchor;

                  pArray[i].leftDirection = pathObj.subPathItems[s].pathPoints[i].leftDirection;

                  pArray[i].rightDirection = pathObj.subPathItems[s].pathPoints[i].rightDirection;


                  pathArray[pathArray.length] = new Array();

                  pathArray[pathArray.length - 1] = new SubPathInfo();

                  pathArray[pathArray.length - 1].operation = pathObj.subPathItems[s].operation;

                  pathArray[pathArray.length - 1].closed = pathObj.subPathItems[s].closed;

                  pathArray[pathArray.length - 1].entireSubPath = pArray;


                  return pathArray;


                  ////// create number //////

                  function makeNumber (myDocument, theNumber, theX, theY) {

                  var textLayer = myDocument.artLayers.add();

                  textLayer.kind = LayerKind.TEXT;

                  textLayer.blendMode = BlendMode.NORMAL;

                  textLayer.opacity = 100;

                  var myTextRef = textLayer.textItem;

                  myTextRef.size = 12;

                  myTextRef.justification = Justification.CENTER;

                  myTextRef.font = "Courier";

                  var newColor = new SolidColor();

                  newColor.rgb.red = 0;

                  newColor.rgb.green = 0;

                  newColor.rgb.blue = 0;

                  myTextRef.color = newColor;

                  myTextRef.position = new Array(theX, theY);

                  myTextRef.contents = theNumber;


                  ////// the fill-layer-function //////

                  function makeFillLayer (theName, theHue, theSat, theBright) {

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

                  var idsetd = charIDToTypeID( "setd" );

                      var desc4 = new ActionDescriptor();

                      var idnull = charIDToTypeID( "null" );

                          var ref2 = new ActionReference();

                          var idClr = charIDToTypeID( "Clr " );

                          var idFrgC = charIDToTypeID( "FrgC" );

                          ref2.putProperty( idClr, idFrgC );

                      desc4.putReference( idnull, ref2 );

                      var idT = charIDToTypeID( "T   " ); 

                          var desc5 = new ActionDescriptor();

                          var idH = charIDToTypeID( "H   " );

                          var idAng = charIDToTypeID( "#Ang" );

                          desc5.putUnitDouble( idH, idAng, theHue );

                          var idStrt = charIDToTypeID( "Strt" );

                          desc5.putDouble( idStrt, theSat );

                          var idBrgh = charIDToTypeID( "Brgh" );

                          desc5.putDouble( idBrgh, theBright );

                      var idHSBC = charIDToTypeID( "HSBC" );

                      desc4.putObject( idT, idHSBC, desc5 );

                  executeAction( idsetd, desc4, DialogModes.NO );

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

                  var id212 = charIDToTypeID( "Mk  " );

                  var desc39 = new ActionDescriptor();

                  var id213 = charIDToTypeID( "null" );

                  var ref27 = new ActionReference();

                  var id214 = stringIDToTypeID( "contentLayer" );

                  ref27.putClass( id214 ); desc39.putReference( id213, ref27 );

                  var id215 = charIDToTypeID( "Usng" );

                  var desc40 = new ActionDescriptor();

                  var id216 = charIDToTypeID( "Type" );

                  var id217 = stringIDToTypeID( "solidColorLayer" );

                  desc40.putClass( id216, id217 );

                  var id218 = stringIDToTypeID( "contentLayer" );

                  desc39.putObject( id215, id218, desc40 );

                  executeAction( id212, desc39, DialogModes.NO );

                  app.activeDocument.activeLayer.name = theName;

                  return app.activeDocument.activeLayer


                  ////// function to create path from array with one array per point that holds anchor, leftdirection, etc, 2010 //////

                  function createPath10 (theArray, thePathName) {

                  var originalRulerUnits = app.preferences.rulerUnits;

                  app.preferences.rulerUnits = Units.POINTS;

                  lineSubPathArray = new Array ();

                  if (theArray[theArray.length - 1].constructor != Array) {var numberOfPaths = theArray.length - 1}

                  else {var numberOfPaths = theArray.length};

                  for (var b = 0; b < numberOfPaths; b++) {

                  var lineArray = new Array ();

                  lineSubPathArray[b] = new SubPathInfo();

                  if (theArray[b][theArray[b].length - 1].constructor == Array) {

                  lineSubPathArray[b].closed = true;

                  var numberOfPoints = theArray[b].length


                  else {

                  lineSubPathArray[b].closed = theArray[b][theArray[b].length - 1]

                  var numberOfPoints = theArray[b].length - 1


                  for (c = 0; c < numberOfPoints; c++) {

                  lineArray[c] = new PathPointInfo;

                  switch (theArray[b][c][3]) {

                  case "CORNER":

                  lineArray[c].kind = PointKind.CORNERPOINT;


                  case "SMOOTH":

                  lineArray[c].kind = PointKind.SMOOTHPOINT;



                  lineArray[c].kind = PointKind.CORNERPOINT;



                  lineArray[c].anchor = theArray[b][c][0];

                  if (theArray[b][c][1].length == 2) {lineArray[c].leftDirection = theArray[b][c][1]}

                  else {lineArray[c].leftDirection = theArray[b][c][0]};

                  if (theArray[b][c][2].length == 2) {lineArray[c].rightDirection = theArray[b][c][2]}

                  else {lineArray[c].rightDirection = theArray[b][c][0]};


                  lineSubPathArray[b].operation = ShapeOperation.SHAPEXOR;

                  lineSubPathArray[b].entireSubPath = lineArray;


                  var myPathItem = app.activeDocument.pathItems.add(thePathName, lineSubPathArray);

                  app.preferences.rulerUnits = originalRulerUnits;

                  return myPathItem


                  • 6. Re: Connect-the-dots in photoshop
                    Muppet Mark-QAl63s Level 4

                    The thing I was talking about is 'countItems' and is accessible to script via the DOM in CS5 however it is a feature of the extended version.


                    Picture 1.png

                    • 7. Re: Connect-the-dots in photoshop
                      Michael L Hale Level 5

                      countItems and countItem is also in the CS4 DOM if you have the extended version of Photoshop.

                      • 8. Re: Connect-the-dots in photoshop
                        Muppet Mark-QAl63s Level 4

                        Mike, I have never had to deal with this before but while on the topic of extended features… How do you tell the difference from script?


                        #target photoshop


                        Do you need to parse something from build? it returns…

                        12.0 (12.0x20100407 [20100407.r.1103 2010/04/07:14:00:00 cutoff; r branch]) © 1990-2010 Adobe Systems Incorporated


                        ESTK Data Browser has app listed as photoshop-12.032 is that it?


                        Is there a way to turn off that predictive text in ESTK too?

                        • 9. Re: Connect-the-dots in photoshop
                          Michael L Hale Level 5

                          Here is how to tell if Photoshop is extended from a script.

                          var isExtendedVersion = app.featureEnabled('photoshop/extended');

                          photoshop-12.032 is the BridgeTalk.appSpecifier for Photoshop CS5 running in 32bit mode. BridgeTalk.appSpecifier will return just 'photoshop'.

                          • 10. Re: Connect-the-dots in photoshop
                            Muppet Mark-QAl63s Level 4

                            Doh! Looked as far as properties NOT methods thanks all the same now I Knows…