1cfd74d65d832137e20e193c960802afba73b5d38sm/*
2cfd74d65d832137e20e193c960802afba73b5d38sm * Copyright (C) 2008 The Android Open Source Project
3cfd74d65d832137e20e193c960802afba73b5d38sm *
4cfd74d65d832137e20e193c960802afba73b5d38sm * Licensed under the Apache License, Version 2.0 (the "License");
5cfd74d65d832137e20e193c960802afba73b5d38sm * you may not use this file except in compliance with the License.
6cfd74d65d832137e20e193c960802afba73b5d38sm * You may obtain a copy of the License at
7cfd74d65d832137e20e193c960802afba73b5d38sm *
8cfd74d65d832137e20e193c960802afba73b5d38sm *      http://www.apache.org/licenses/LICENSE-2.0
9cfd74d65d832137e20e193c960802afba73b5d38sm *
10cfd74d65d832137e20e193c960802afba73b5d38sm * Unless required by applicable law or agreed to in writing, software
11cfd74d65d832137e20e193c960802afba73b5d38sm * distributed under the License is distributed on an "AS IS" BASIS,
12cfd74d65d832137e20e193c960802afba73b5d38sm * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cfd74d65d832137e20e193c960802afba73b5d38sm * See the License for the specific language governing permissions and
14cfd74d65d832137e20e193c960802afba73b5d38sm * limitations under the License.
15cfd74d65d832137e20e193c960802afba73b5d38sm */
16cfd74d65d832137e20e193c960802afba73b5d38sm
17cfd74d65d832137e20e193c960802afba73b5d38sm /**
18cfd74d65d832137e20e193c960802afba73b5d38sm * @fileoverview This implements a Photoshop script that can be used to generate
19cfd74d65d832137e20e193c960802afba73b5d38sm * collision information for the AndouKun game engine.  This tool walks over
20cfd74d65d832137e20e193c960802afba73b5d38sm * each path in the current document and generates a list of edges and normals
21cfd74d65d832137e20e193c960802afba73b5d38sm * in a new document.  It is intended to be used on a file containing
22cfd74d65d832137e20e193c960802afba73b5d38sm * graphical representations of the collision tiles used by the engine.  Each
23cfd74d65d832137e20e193c960802afba73b5d38sm * path in the file must be closed and may not contain any curved points
24cfd74d65d832137e20e193c960802afba73b5d38sm * (the tool assumes that the line between any two points in a given path is
25cfd74d65d832137e20e193c960802afba73b5d38sm * straight).  Only one shape may be contained per path layer (each path must go
26cfd74d65d832137e20e193c960802afba73b5d38sm * in its own path layer).  This tool can also output a graphical version of its
27cfd74d65d832137e20e193c960802afba73b5d38sm * edge calculation for debugging purposes.
28cfd74d65d832137e20e193c960802afba73b5d38sm */
29cfd74d65d832137e20e193c960802afba73b5d38sm
30cfd74d65d832137e20e193c960802afba73b5d38sm/* If set to true, the computation will be rendered graphically to the output
31cfd74d65d832137e20e193c960802afba73b5d38sm   file */
32cfd74d65d832137e20e193c960802afba73b5d38smvar drawOutput = false;
33cfd74d65d832137e20e193c960802afba73b5d38sm/* If true, the computation will be printed in a text layer in the
34cfd74d65d832137e20e193c960802afba73b5d38sm   output file.*/
35cfd74d65d832137e20e193c960802afba73b5d38smvar printOutput = true;
36cfd74d65d832137e20e193c960802afba73b5d38sm
37cfd74d65d832137e20e193c960802afba73b5d38sm// Back up the ruler units that this file uses before switching to pixel units.
38cfd74d65d832137e20e193c960802afba73b5d38smvar defaultRulerUnits = app.preferences.rulerUnits;
39cfd74d65d832137e20e193c960802afba73b5d38smapp.preferences.rulerUnits = Units.PIXELS;
40cfd74d65d832137e20e193c960802afba73b5d38sm
41cfd74d65d832137e20e193c960802afba73b5d38smvar tileSizeX = prompt("Tile pixel width:");
42cfd74d65d832137e20e193c960802afba73b5d38smvar tileSizeY = prompt("Tile pixel height:");
43cfd74d65d832137e20e193c960802afba73b5d38sm
44cfd74d65d832137e20e193c960802afba73b5d38smvar documentWidth = app.activeDocument.width;
45cfd74d65d832137e20e193c960802afba73b5d38smvar documentHeight = app.activeDocument.height;
46cfd74d65d832137e20e193c960802afba73b5d38sm
47cfd74d65d832137e20e193c960802afba73b5d38smvar tilesPerRow = documentWidth / tileSizeX;
48cfd74d65d832137e20e193c960802afba73b5d38smvar tilesPerColumn = documentHeight / tileSizeY;
49cfd74d65d832137e20e193c960802afba73b5d38sm
50cfd74d65d832137e20e193c960802afba73b5d38smvar tiles = new Array();
51cfd74d65d832137e20e193c960802afba73b5d38smtiles.length = tilesPerRow * tilesPerColumn;
52cfd74d65d832137e20e193c960802afba73b5d38sm
53cfd74d65d832137e20e193c960802afba73b5d38sm// Walk the list of paths and extract edges and normals.  Store these in
54cfd74d65d832137e20e193c960802afba73b5d38sm// an array by tile.
55cfd74d65d832137e20e193c960802afba73b5d38smvar pathList = app.activeDocument.pathItems;
56cfd74d65d832137e20e193c960802afba73b5d38smfor (pathIndex = 0; pathIndex < pathList.length; pathIndex++) {
57cfd74d65d832137e20e193c960802afba73b5d38sm  var main_path = pathList[pathIndex];
58cfd74d65d832137e20e193c960802afba73b5d38sm  if (main_path) {
59cfd74d65d832137e20e193c960802afba73b5d38sm    var itemList = main_path.subPathItems;
60cfd74d65d832137e20e193c960802afba73b5d38sm    if (!itemList) {
61cfd74d65d832137e20e193c960802afba73b5d38sm      alert("Path has no sub items!");
62cfd74d65d832137e20e193c960802afba73b5d38sm    } else {
63cfd74d65d832137e20e193c960802afba73b5d38sm      for (var x = 0; x < itemList.length; x++) {
64cfd74d65d832137e20e193c960802afba73b5d38sm        var item = itemList[x];
65cfd74d65d832137e20e193c960802afba73b5d38sm        var points = item.pathPoints;
66cfd74d65d832137e20e193c960802afba73b5d38sm        var tile = new Object;
67cfd74d65d832137e20e193c960802afba73b5d38sm        tile.edges = new Array();
68cfd74d65d832137e20e193c960802afba73b5d38sm
69cfd74d65d832137e20e193c960802afba73b5d38sm        var totalX = 0;
70cfd74d65d832137e20e193c960802afba73b5d38sm        var totalY = 0;
71cfd74d65d832137e20e193c960802afba73b5d38sm        for (var y = 0; y < points.length; y++) {
72cfd74d65d832137e20e193c960802afba73b5d38sm          var firstPoint = points[y];
73cfd74d65d832137e20e193c960802afba73b5d38sm          var lastPoint = points[(y + 1) % points.length];
74cfd74d65d832137e20e193c960802afba73b5d38sm
75cfd74d65d832137e20e193c960802afba73b5d38sm          var edge = new Object;
76cfd74d65d832137e20e193c960802afba73b5d38sm
77cfd74d65d832137e20e193c960802afba73b5d38sm          edge.startX = firstPoint.anchor[0];
78cfd74d65d832137e20e193c960802afba73b5d38sm          edge.startY = firstPoint.anchor[1];
79cfd74d65d832137e20e193c960802afba73b5d38sm
80cfd74d65d832137e20e193c960802afba73b5d38sm          edge.endX = lastPoint.anchor[0];
81cfd74d65d832137e20e193c960802afba73b5d38sm          edge.endY = lastPoint.anchor[1];
82cfd74d65d832137e20e193c960802afba73b5d38sm
83cfd74d65d832137e20e193c960802afba73b5d38sm          var normalX = -(edge.endY - edge.startY);
84cfd74d65d832137e20e193c960802afba73b5d38sm          var normalY = edge.endX - edge.startX;
85cfd74d65d832137e20e193c960802afba73b5d38sm
86cfd74d65d832137e20e193c960802afba73b5d38sm          var normalLength = Math.sqrt((normalX * normalX) + (normalY * normalY));
87cfd74d65d832137e20e193c960802afba73b5d38sm          normalX /= normalLength;
88cfd74d65d832137e20e193c960802afba73b5d38sm          normalY /= normalLength;
89cfd74d65d832137e20e193c960802afba73b5d38sm
90cfd74d65d832137e20e193c960802afba73b5d38sm          edge.normalX = normalX;
91cfd74d65d832137e20e193c960802afba73b5d38sm          edge.normalY = normalY;
92cfd74d65d832137e20e193c960802afba73b5d38sm
93cfd74d65d832137e20e193c960802afba73b5d38sm          if (normalX == 0 && normalY == 0) {
94cfd74d65d832137e20e193c960802afba73b5d38sm            alert("Zero length normal calculated at path " + pathIndex);
95cfd74d65d832137e20e193c960802afba73b5d38sm          }
96cfd74d65d832137e20e193c960802afba73b5d38sm
97cfd74d65d832137e20e193c960802afba73b5d38sm          var normalLength2 = Math.sqrt((normalX * normalX) + (normalY * normalY));
98cfd74d65d832137e20e193c960802afba73b5d38sm          if (normalLength2 > 1 || normalLength2 < 0.9) {
99cfd74d65d832137e20e193c960802afba73b5d38sm            alert("Normal of invalid length (" + normalLength2 + ") found at path " + pathIndex);
100cfd74d65d832137e20e193c960802afba73b5d38sm          }
101cfd74d65d832137e20e193c960802afba73b5d38sm
102cfd74d65d832137e20e193c960802afba73b5d38sm          totalX += edge.endX;
103cfd74d65d832137e20e193c960802afba73b5d38sm          totalY += edge.endY;
104cfd74d65d832137e20e193c960802afba73b5d38sm
105cfd74d65d832137e20e193c960802afba73b5d38sm          var width = edge.endX - edge.startX;
106cfd74d65d832137e20e193c960802afba73b5d38sm          var height = edge.endY - edge.startY;
107cfd74d65d832137e20e193c960802afba73b5d38sm
108cfd74d65d832137e20e193c960802afba73b5d38sm          edge.centerX = edge.endX - (width / 2);
109cfd74d65d832137e20e193c960802afba73b5d38sm          edge.centerY = edge.endY - (height / 2);
110cfd74d65d832137e20e193c960802afba73b5d38sm
111cfd74d65d832137e20e193c960802afba73b5d38sm          tile.edges.push(edge);
112cfd74d65d832137e20e193c960802afba73b5d38sm        }
113cfd74d65d832137e20e193c960802afba73b5d38sm
114cfd74d65d832137e20e193c960802afba73b5d38sm        totalX /= points.length;
115cfd74d65d832137e20e193c960802afba73b5d38sm        totalY /= points.length;
116cfd74d65d832137e20e193c960802afba73b5d38sm        tile.centerX = totalX;
117cfd74d65d832137e20e193c960802afba73b5d38sm        tile.centerY = totalY;
118cfd74d65d832137e20e193c960802afba73b5d38sm
119cfd74d65d832137e20e193c960802afba73b5d38sm        var column = Math.floor(tile.centerX / tileSizeX);
120cfd74d65d832137e20e193c960802afba73b5d38sm        var row = Math.floor(tile.centerY / tileSizeY);
121cfd74d65d832137e20e193c960802afba73b5d38sm
122cfd74d65d832137e20e193c960802afba73b5d38sm        tile.xOffset = column * tileSizeX;
123cfd74d65d832137e20e193c960802afba73b5d38sm        tile.yOffset = row * tileSizeY;
124cfd74d65d832137e20e193c960802afba73b5d38sm
125cfd74d65d832137e20e193c960802afba73b5d38sm        tile.centerX -= tile.xOffset;
126cfd74d65d832137e20e193c960802afba73b5d38sm        tile.centerY -= tile.yOffset;
127cfd74d65d832137e20e193c960802afba73b5d38sm
128cfd74d65d832137e20e193c960802afba73b5d38sm        var tileIndex = Math.floor(row * tilesPerRow + column);
129cfd74d65d832137e20e193c960802afba73b5d38sm        tiles[tileIndex] = tile;
130cfd74d65d832137e20e193c960802afba73b5d38sm
131cfd74d65d832137e20e193c960802afba73b5d38sm      }
132cfd74d65d832137e20e193c960802afba73b5d38sm    }
133cfd74d65d832137e20e193c960802afba73b5d38sm  }
134cfd74d65d832137e20e193c960802afba73b5d38sm}
135cfd74d65d832137e20e193c960802afba73b5d38sm
136cfd74d65d832137e20e193c960802afba73b5d38smvar outputString = "";
137cfd74d65d832137e20e193c960802afba73b5d38sm
138cfd74d65d832137e20e193c960802afba73b5d38sm// For each tile print the edges to a string.
139cfd74d65d832137e20e193c960802afba73b5d38smfor (var x = 0; x < tiles.length; x++) {
140cfd74d65d832137e20e193c960802afba73b5d38sm  if (tiles[x]) {
141cfd74d65d832137e20e193c960802afba73b5d38sm    var tile = tiles[x];
142cfd74d65d832137e20e193c960802afba73b5d38sm    for (var y = 0; y < tile.edges.length; y++) {
143cfd74d65d832137e20e193c960802afba73b5d38sm      var edge = tile.edges[y];
144cfd74d65d832137e20e193c960802afba73b5d38sm
145cfd74d65d832137e20e193c960802afba73b5d38sm      // convert to tile space
146cfd74d65d832137e20e193c960802afba73b5d38sm      edge.startX -= tile.xOffset;
147cfd74d65d832137e20e193c960802afba73b5d38sm      edge.startY -= tile.yOffset;
148cfd74d65d832137e20e193c960802afba73b5d38sm      edge.endX -= tile.xOffset;
149cfd74d65d832137e20e193c960802afba73b5d38sm      edge.endY -= tile.yOffset;
150cfd74d65d832137e20e193c960802afba73b5d38sm      edge.centerX -= tile.xOffset;
151cfd74d65d832137e20e193c960802afba73b5d38sm      edge.centerY -= tile.yOffset;
152cfd74d65d832137e20e193c960802afba73b5d38sm
153cfd74d65d832137e20e193c960802afba73b5d38sm      // The normals that we calculated previously might be facing the wrong
154cfd74d65d832137e20e193c960802afba73b5d38sm      // direction.  Detect this case and correct it by checking to see if
155cfd74d65d832137e20e193c960802afba73b5d38sm      // adding the normal to a point on the edge moves the point closer or
156cfd74d65d832137e20e193c960802afba73b5d38sm      // further from the center of the shape.
157cfd74d65d832137e20e193c960802afba73b5d38sm      if (Math.abs(edge.centerX - tile.centerX) >
158cfd74d65d832137e20e193c960802afba73b5d38sm            Math.abs((edge.centerX + edge.normalX) - tile.centerX)) {
159cfd74d65d832137e20e193c960802afba73b5d38sm        edge.normalX *= -1;
160cfd74d65d832137e20e193c960802afba73b5d38sm        edge.normalY *= -1;
161cfd74d65d832137e20e193c960802afba73b5d38sm      }
162cfd74d65d832137e20e193c960802afba73b5d38sm
163cfd74d65d832137e20e193c960802afba73b5d38sm      if (Math.abs(edge.centerY - tile.centerY) >
164cfd74d65d832137e20e193c960802afba73b5d38sm            Math.abs((edge.centerY + edge.normalY) - tile.centerY)) {
165cfd74d65d832137e20e193c960802afba73b5d38sm        edge.normalX *= -1;
166cfd74d65d832137e20e193c960802afba73b5d38sm        edge.normalY *= -1;
167cfd74d65d832137e20e193c960802afba73b5d38sm      }
168cfd74d65d832137e20e193c960802afba73b5d38sm
169cfd74d65d832137e20e193c960802afba73b5d38sm
170cfd74d65d832137e20e193c960802afba73b5d38sm      // Convert to left-handed GL space (the origin is at the bottom-left).
171cfd74d65d832137e20e193c960802afba73b5d38sm      edge.normalY *= -1;
172cfd74d65d832137e20e193c960802afba73b5d38sm      edge.startY = tileSizeY - edge.startY;
173cfd74d65d832137e20e193c960802afba73b5d38sm      edge.endY = tileSizeY - edge.endY;
174cfd74d65d832137e20e193c960802afba73b5d38sm      edge.centerY = tileSizeY - edge.centerY;
175cfd74d65d832137e20e193c960802afba73b5d38sm
176cfd74d65d832137e20e193c960802afba73b5d38sm      outputString += x + ":" + Math.floor(edge.startX) + "," +
177cfd74d65d832137e20e193c960802afba73b5d38sm          Math.floor(edge.startY) + ":" + Math.floor(edge.endX) + "," +
178cfd74d65d832137e20e193c960802afba73b5d38sm          Math.floor(edge.endY) + ":" + edge.normalX + "," + edge.normalY +
179cfd74d65d832137e20e193c960802afba73b5d38sm          "\r";
180cfd74d65d832137e20e193c960802afba73b5d38sm    }
181cfd74d65d832137e20e193c960802afba73b5d38sm  }
182cfd74d65d832137e20e193c960802afba73b5d38sm}
183cfd74d65d832137e20e193c960802afba73b5d38sm
184cfd74d65d832137e20e193c960802afba73b5d38sm
185cfd74d65d832137e20e193c960802afba73b5d38smif (outputString.length > 0) {
186cfd74d65d832137e20e193c960802afba73b5d38sm
187cfd74d65d832137e20e193c960802afba73b5d38sm    var newDoc = app.documents.add(600, 700, 72.0, "Edge Output",
188cfd74d65d832137e20e193c960802afba73b5d38sm        NewDocumentMode.RGB);
189cfd74d65d832137e20e193c960802afba73b5d38sm
190cfd74d65d832137e20e193c960802afba73b5d38sm    if (drawOutput) {
191cfd74d65d832137e20e193c960802afba73b5d38sm      // Render the edges and normals to the new document.
192cfd74d65d832137e20e193c960802afba73b5d38sm      var pathLayer = newDoc.artLayers.add();
193cfd74d65d832137e20e193c960802afba73b5d38sm      newDoc.activeLayer = pathLayer;
194cfd74d65d832137e20e193c960802afba73b5d38sm
195cfd74d65d832137e20e193c960802afba73b5d38sm      // draw the edges to make sure everything works
196cfd74d65d832137e20e193c960802afba73b5d38sm      var black = new SolidColor;
197cfd74d65d832137e20e193c960802afba73b5d38sm      black.rgb.red = 0;
198cfd74d65d832137e20e193c960802afba73b5d38sm      black.rgb.blue = 0;
199cfd74d65d832137e20e193c960802afba73b5d38sm      black.rgb.green = 0;
200cfd74d65d832137e20e193c960802afba73b5d38sm
201cfd74d65d832137e20e193c960802afba73b5d38sm      var redColor = new SolidColor;
202cfd74d65d832137e20e193c960802afba73b5d38sm      redColor.rgb.red = 255;
203cfd74d65d832137e20e193c960802afba73b5d38sm      redColor.rgb.blue = 0;
204cfd74d65d832137e20e193c960802afba73b5d38sm      redColor.rgb.green = 0;
205cfd74d65d832137e20e193c960802afba73b5d38sm
206cfd74d65d832137e20e193c960802afba73b5d38sm      var greenColor = new SolidColor;
207cfd74d65d832137e20e193c960802afba73b5d38sm      greenColor.rgb.red = 0;
208cfd74d65d832137e20e193c960802afba73b5d38sm      greenColor.rgb.blue = 0;
209cfd74d65d832137e20e193c960802afba73b5d38sm      greenColor.rgb.green = 255;
210cfd74d65d832137e20e193c960802afba73b5d38sm
211cfd74d65d832137e20e193c960802afba73b5d38sm      var blueColor = new SolidColor;
212cfd74d65d832137e20e193c960802afba73b5d38sm      blueColor.rgb.red = 0;
213cfd74d65d832137e20e193c960802afba73b5d38sm      blueColor.rgb.blue = 255;
214cfd74d65d832137e20e193c960802afba73b5d38sm      blueColor.rgb.green = 0;
215cfd74d65d832137e20e193c960802afba73b5d38sm
216cfd74d65d832137e20e193c960802afba73b5d38sm      var lineIndex = 0;
217cfd74d65d832137e20e193c960802afba73b5d38sm      for (var x = 0; x < tiles.length; x++) {
218cfd74d65d832137e20e193c960802afba73b5d38sm        if (tiles[x]) {
219cfd74d65d832137e20e193c960802afba73b5d38sm          var tile = tiles[x];
220cfd74d65d832137e20e193c960802afba73b5d38sm          var lineArray = new Array();
221cfd74d65d832137e20e193c960802afba73b5d38sm          var offsetX = Math.floor(x % tilesPerRow) * tileSizeX;
222cfd74d65d832137e20e193c960802afba73b5d38sm          var offsetY = Math.floor(x / tilesPerRow) * tileSizeY;
223cfd74d65d832137e20e193c960802afba73b5d38sm
224cfd74d65d832137e20e193c960802afba73b5d38sm          for (var y = 0; y < tile.edges.length; y++) {
225cfd74d65d832137e20e193c960802afba73b5d38sm            var edge = tile.edges[y];
226cfd74d65d832137e20e193c960802afba73b5d38sm
227cfd74d65d832137e20e193c960802afba73b5d38sm            lineArray[y] = Array(offsetX + edge.startX, offsetY + edge.startY);
228cfd74d65d832137e20e193c960802afba73b5d38sm          }
229cfd74d65d832137e20e193c960802afba73b5d38sm
230cfd74d65d832137e20e193c960802afba73b5d38sm          // I tried to do this by stroking paths, but the documentation
231cfd74d65d832137e20e193c960802afba73b5d38sm          // provided by Adobe is faulty (their sample code doesn't run).  The
232cfd74d65d832137e20e193c960802afba73b5d38sm          // same thing can be accomplished with selections instead.
233cfd74d65d832137e20e193c960802afba73b5d38sm          newDoc.selection.select(lineArray);
234cfd74d65d832137e20e193c960802afba73b5d38sm          newDoc.selection.stroke(black, 2);
235cfd74d65d832137e20e193c960802afba73b5d38sm
236cfd74d65d832137e20e193c960802afba73b5d38sm          for (var y = 0; y < tile.edges.length; y++) {
237cfd74d65d832137e20e193c960802afba73b5d38sm            var edge = tile.edges[y];
238cfd74d65d832137e20e193c960802afba73b5d38sm
239cfd74d65d832137e20e193c960802afba73b5d38sm             var normalX = Math.round(tile.centerX +
240cfd74d65d832137e20e193c960802afba73b5d38sm                (edge.normalX * (tileSizeX / 2)));
241cfd74d65d832137e20e193c960802afba73b5d38sm             var normalY = Math.round(tile.centerY +
242cfd74d65d832137e20e193c960802afba73b5d38sm                (edge.normalY * (tileSizeY / 2)));
243cfd74d65d832137e20e193c960802afba73b5d38sm
244cfd74d65d832137e20e193c960802afba73b5d38sm             var tileCenterArray = new Array();
245cfd74d65d832137e20e193c960802afba73b5d38sm             tileCenterArray[0] = new Array(offsetX + tile.centerX - 1,
246cfd74d65d832137e20e193c960802afba73b5d38sm                offsetY + tile.centerY - 1);
247cfd74d65d832137e20e193c960802afba73b5d38sm             tileCenterArray[1] = new Array(offsetX + tile.centerX - 1,
248cfd74d65d832137e20e193c960802afba73b5d38sm                offsetY + tile.centerY + 1);
249cfd74d65d832137e20e193c960802afba73b5d38sm             tileCenterArray[2] = new Array(offsetX + tile.centerX + 1,
250cfd74d65d832137e20e193c960802afba73b5d38sm                offsetY + tile.centerY + 1);
251cfd74d65d832137e20e193c960802afba73b5d38sm             tileCenterArray[3] = new Array(offsetX + tile.centerX + 1,
252cfd74d65d832137e20e193c960802afba73b5d38sm                offsetY + tile.centerY - 1);
253cfd74d65d832137e20e193c960802afba73b5d38sm             tileCenterArray[4] = new Array(offsetX + normalX - 1,
254cfd74d65d832137e20e193c960802afba73b5d38sm                offsetY + normalY - 1);
255cfd74d65d832137e20e193c960802afba73b5d38sm             tileCenterArray[5] = new Array(offsetX + normalX + 1,
256cfd74d65d832137e20e193c960802afba73b5d38sm                offsetY + normalY + 1);
257cfd74d65d832137e20e193c960802afba73b5d38sm             tileCenterArray[6] = new Array(offsetX + tile.centerX,
258cfd74d65d832137e20e193c960802afba73b5d38sm                offsetY + tile.centerY);
259cfd74d65d832137e20e193c960802afba73b5d38sm
260cfd74d65d832137e20e193c960802afba73b5d38sm             newDoc.selection.select(tileCenterArray);
261cfd74d65d832137e20e193c960802afba73b5d38sm             newDoc.selection.fill(redColor);
262cfd74d65d832137e20e193c960802afba73b5d38sm
263cfd74d65d832137e20e193c960802afba73b5d38sm             var centerArray = new Array();
264cfd74d65d832137e20e193c960802afba73b5d38sm             centerArray[0] = new Array(offsetX + edge.centerX - 1,
265cfd74d65d832137e20e193c960802afba73b5d38sm                offsetY + edge.centerY - 1);
266cfd74d65d832137e20e193c960802afba73b5d38sm             centerArray[1] = new Array(offsetX + edge.centerX - 1,
267cfd74d65d832137e20e193c960802afba73b5d38sm                offsetY + edge.centerY + 1);
268cfd74d65d832137e20e193c960802afba73b5d38sm             centerArray[2] = new Array(offsetX + edge.centerX + 1,
269cfd74d65d832137e20e193c960802afba73b5d38sm                offsetY + edge.centerY + 1);
270cfd74d65d832137e20e193c960802afba73b5d38sm             centerArray[3] = new Array(offsetX + edge.centerX + 1,
271cfd74d65d832137e20e193c960802afba73b5d38sm                offsetY + edge.centerY - 1);
272cfd74d65d832137e20e193c960802afba73b5d38sm
273cfd74d65d832137e20e193c960802afba73b5d38sm             newDoc.selection.select(centerArray);
274cfd74d65d832137e20e193c960802afba73b5d38sm             newDoc.selection.fill(greenColor);
275cfd74d65d832137e20e193c960802afba73b5d38sm
276cfd74d65d832137e20e193c960802afba73b5d38sm          }
277cfd74d65d832137e20e193c960802afba73b5d38sm
278cfd74d65d832137e20e193c960802afba73b5d38sm        }
279cfd74d65d832137e20e193c960802afba73b5d38sm      }
280cfd74d65d832137e20e193c960802afba73b5d38sm    }
281cfd74d65d832137e20e193c960802afba73b5d38sm
282cfd74d65d832137e20e193c960802afba73b5d38sm    if (printOutput) {
283cfd74d65d832137e20e193c960802afba73b5d38sm      var textLayer = newDoc.artLayers.add();
284cfd74d65d832137e20e193c960802afba73b5d38sm      textLayer.kind = LayerKind.TEXT;
285cfd74d65d832137e20e193c960802afba73b5d38sm      textLayer.textItem.contents = outputString;
286cfd74d65d832137e20e193c960802afba73b5d38sm    }
287cfd74d65d832137e20e193c960802afba73b5d38sm}
288cfd74d65d832137e20e193c960802afba73b5d38sm
289cfd74d65d832137e20e193c960802afba73b5d38smpreferences.rulerUnits = defaultRulerUnits;
290cfd74d65d832137e20e193c960802afba73b5d38sm
291cfd74d65d832137e20e193c960802afba73b5d38sm// Convenience function for clamping negative values to zero.  Trying to select
292cfd74d65d832137e20e193c960802afba73b5d38sm// areas outside the canvas causes Bad Things.
293cfd74d65d832137e20e193c960802afba73b5d38smfunction clamp(input) {
294cfd74d65d832137e20e193c960802afba73b5d38sm  if (input < 0) {
295cfd74d65d832137e20e193c960802afba73b5d38sm    return 0;
296cfd74d65d832137e20e193c960802afba73b5d38sm  }
297cfd74d65d832137e20e193c960802afba73b5d38sm  return input;
298cfd74d65d832137e20e193c960802afba73b5d38sm}
299