diff --git a/CHANGELOG.md b/CHANGELOG.md
index a5e9953..50bfef5 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,20 +6,52 @@
+## addAnchorPoints.js
+### 1.1.0 (2024-06-01)
+### Added
+- Anchor points for type on a path and area type are now supported.
+- Added the function to check the illustrator version.
+
+
+
## addNumericSeparators.js
### 1.2.0 (2024-04-29)
### Added
-- Added the ability to add commas only to text within a selection.
+- Added the function to add commas only to text within a selection.
### 1.1.0 (2022-11-13)
### Added
- Modified to run the script in the text editing state.
+## alignInCenterOfSpace(Horizontal).js
+### 1.1.0 (2024-06-01)
+### Added
+- The Align panel menu > Use Preview Bounds is now supported.
+- Added the function to check the illustrator version.
+
+
+
+## alignInCenterOfSpace(Vertical).js
+### 1.1.0 (2024-06-01)
+### Added
+- The Align panel menu > Use Preview Bounds is now supported.
+- Added the function to check the illustrator version.
+
+
+
+## alignObjects.js
+### 1.1.0 (2024-06-01)
+### Added
+- Added supported units.
+- The up and down arrow keys can now be used to increase or decrease the value.
+
+
+
## arrangeWindows.js
### 1.0.1 (2024-04-06)
### Added
-- Version check added.
+- Added the function to check the illustrator version.
@@ -44,6 +76,15 @@
+## convertAllAnchorPointsToCorner.js
+### 1.1.0 (2024-06-01)
+### Added
+- Anchor points for type on a path and area type are now supported.
+- Added the function to convert all anchor points or only selected anchor points when anchor points are selected with the Direct Selection Tool.
+- Added the function to check the illustrator version.
+
+
+
## copyLineDown.js
### 1.0.1 (2022-10-28)
### Bug Fixes
@@ -91,6 +132,15 @@
+## createTextParallelToPathSegment.js
+### 1.0.1 (2024-06-01)
+### Added
+- The up and down arrow keys can now be used to increase or decrease the value.
+### Bug Fixes
+- Fixed the problem of not being able to undo with the esc key due to localization.
+
+
+
## createThreadedText.js
### 1.1.0 (2024-04-29)
### Added
@@ -128,6 +178,22 @@
+## distributeInSpace(Horizontal).js
+### 1.1.0 (2024-06-01)
+### Added
+- The Align panel menu > Use Preview Bounds is now supported.
+- Added the function to check the illustrator version.
+
+
+
+## distributeInSpace(Vertical).js
+### 1.1.0 (2024-06-01)
+### Added
+- The Align panel menu > Use Preview Bounds is now supported.
+- Added the function to check the illustrator version.
+
+
+
## drawCircumscribedCircle.js
### 1.1.0 (2023-04-29)
### Features
@@ -135,7 +201,33 @@
+## drawRectangle.js
+### 1.1.0 (2024-06-01)
+### Added
+- Added the function to ignore grouped objects.
+- Added preview function.
+- Added supported units.
+- Added the function to check the illustrator version.
+
+
+
+## drawShapeOnAnchorPoint.js
+### 1.1.0 (2024-06-01)
+### Added
+- Added the function to draw a shape on all anchor points or only selected anchor points when anchor points are selected with the Direct Selection Tool.
+- Added supported units.
+- Added the function to check the illustrator version.
+### Bug Fixes
+- Fixed the problem of not being able to undo with the esc key due to localization.
+
+
+
## extendHandle.js
+### 1.2.0 (2024-06-01)
+### Added
+- Added supported units.
+- Added the function to check the illustrator version.
+- The up and down arrow keys can now be used to increase or decrease the value.
### 1.1.0 (2023-05-28)
### Features
- Added the function to change the angle.
@@ -143,6 +235,11 @@
## extendLine.js
+### 1.2.0 (2024-06-01)
+### Added
+- Added supported units.
+- Added the function to check the illustrator version.
+- The up and down arrow keys can now be used to increase or decrease the value.
### 1.1.0 (2023-05-14)
### Features
- Added preview function.
@@ -266,6 +363,16 @@
+## rearrangeObjects.js
+### 1.1.0 (2024-06-01)
+### Added
+- Added supported units.
+- The up and down arrow keys can now be used to increase or decrease the value.
+### Bug Fixes
+- Fixed the problem of not being able to undo with the esc key due to localization.
+
+
+
## relinkFileExtension.js
### 1.1.0 (2023-01-15)
### Changes
@@ -345,6 +452,11 @@
## showDimensions.js
+### 2.1.0 (2024-06-01)
+### Added
+- Added the function to show dimensions only selected anchor points when anchor points are selected with the Direct Selection Tool.
+- Added supported units.
+- Added the function to check the illustrator version.
### 2.0.0 (2023-05-14)
### Added
- Curves are now supported.
@@ -369,9 +481,16 @@
## stepAndRepeat.js
+### 2.1.0 (2024-06-01)
+### Added
+- Added supported units.
+- Added the function to check the illustrator version.
+- The up and down arrow keys can now be used to increase or decrease the value.
+### Bug Fixes
+- Fixed preview behavior.
### 2.0.1 (2023-05-14)
### Bug Fixes
-- Work around the problem of being unable to undo the ESC key during localization.
+- Fixed the problem of not being able to undo with the esc key due to localization.
### 2.0.0 (2022-10-08)
### Changes
- The UI has been brought closer to InDesign.
@@ -382,7 +501,7 @@
## syncView.js
### 1.0.1 (2024-04-06)
### Added
-- Version check added.
+- Added the function to check the illustrator version.
### Bug Fixes
- Fixed an issue where multiple openings of the same file would not synchronize.
diff --git a/README.md b/README.md
index 71226d8..2c2ade1 100755
--- a/README.md
+++ b/README.md
@@ -55,46 +55,48 @@ If you find a script that interests you, please download it from [![Download](ht
### Path
[![Download Path.zip](https://img.shields.io/badge/Download-Path.zip-e60012)](https://github.com/sky-chaser-high/adobe-illustrator-scripts/releases/latest/download/Path.zip)
-- [Add Anchor Points](#addAnchorPointsjs)
-- [Align in Center of Space (Horizontal)](#alignInCenterOfSpaceHorizontaljsalignInCenterOfSpaceVerticaljs)
-- [Align in Center of Space (Vertical)](#alignInCenterOfSpaceHorizontaljsalignInCenterOfSpaceVerticaljs)
-- [Align Objects](#alignObjectsjs)
+- [Add Anchor Points](#addAnchorPointsjs) `Update`
+- [Align in Center of Space (Horizontal)](#alignInCenterOfSpaceHorizontaljsalignInCenterOfSpaceVerticaljs) `Update`
+- [Align in Center of Space (Vertical)](#alignInCenterOfSpaceHorizontaljsalignInCenterOfSpaceVerticaljs) `Update`
+- [Align Objects](#alignObjectsjs) `Update`
- [Close Path](#closePathjs)
-- [Convert All Anchor Points to Corner](#convertAllAnchorPointsToCornerjs)
+- [Convert All Anchor Points to Corner](#convertAllAnchorPointsToCornerjs) `Update`
- [Create Grid Lines](#createGridLinesjs)
- [Decrease Selected Anchor Points Clockwise](#decreaseSelectedAnchorPointsCWjsdecreaseSelectedAnchorPointsCCWjs)
- [Decrease Selected Anchor Points Counterclockwise](#decreaseSelectedAnchorPointsCWjsdecreaseSelectedAnchorPointsCCWjs)
- [Disjoin Path](#disjoinPathjs)
-- [Distribute in Space (Horizontal)](#distributeInSpaceHorizontaljsdistributeInSpaceVerticaljs)
-- [Distribute in Space (Vertical)](#distributeInSpaceHorizontaljsdistributeInSpaceVerticaljs)
+- [Distribute in Space (Horizontal)](#distributeInSpaceHorizontaljsdistributeInSpaceVerticaljs) `Update`
+- [Distribute in Space (Vertical)](#distributeInSpaceHorizontaljsdistributeInSpaceVerticaljs) `Update`
- [Draw Circumscribed Circle](#drawCircumscribedCirclejs)
-- [Draw Rectangle](#drawRectanglejs)
-- [Draw Shape on Anchor Point](#drawShapeOnAnchorPointjs)
-- [Extend Handle](#extendHandlejs)
-- [Extend Line](#extendLinejs)
+- [Draw Normal Line](#drawNormalLinejs) `New`
+- [Draw Rectangle](#drawRectanglejs) `Update`
+- [Draw Shape on Anchor Point](#drawShapeOnAnchorPointjs) `Update`
+- [Draw Shape Parallel to Path Segment](#drawShapeParallelToPathSegmentjs) `New`
+- [Extend Handle](#extendHandlejs) `Update`
+- [Extend Line](#extendLinejs) `Update`
- [Fit Guide in Artboard](#fitGuideInArtboardjs)
- [Increase Selected Anchor Points Clockwise](#increaseSelectedAnchorPointsCWjsincreaseSelectedAnchorPointsCCWjs)
- [Increase Selected Anchor Points Counterclockwise](#increaseSelectedAnchorPointsCWjsincreaseSelectedAnchorPointsCCWjs)
- [Move Guides](#moveGuidesjs)
-- [Rearrange Objects](#rearrangeObjectsjs)
+- [Rearrange Objects](#rearrangeObjectsjs) `Update`
- [Remove Color in Guide Object](#removeColorInGuideObjectjs)
- [Select Guides](#selectGuidesjs)
- [Shift Selected Anchor Points Clockwise](#shiftSelectedAnchorPointsCWjsshiftSelectedAnchorPointsCCWjs)
- [Shift Selected Anchor Points Counterclockwise](#shiftSelectedAnchorPointsCWjsshiftSelectedAnchorPointsCCWjs)
-- [Show Dimensions](#showDimensionsjs)
+- [Show Dimensions](#showDimensionsjs) `Update`
- [Shuffle Objects](#shuffleObjectsjs)
-- [Step and Repeat](#stepAndRepeatjs)
+- [Step and Repeat](#stepAndRepeatjs) `Update`
### Text
[![Download Text.zip](https://img.shields.io/badge/Download-Text.zip-e60012)](https://github.com/sky-chaser-high/adobe-illustrator-scripts/releases/latest/download/Text.zip)
-- [Add Numeric Separators](#addNumericSeparatorsjs) `Update`
+- [Add Numeric Separators](#addNumericSeparatorsjs)
- [Convert Type on a Path to Point Type](#convertTypeOnAPathToPointTypejs)
- [Copy Line Down](#copyLineDownjscopyLineUpjs)
- [Copy Line Up](#copyLineDownjscopyLineUpjs)
- [Copy Line (empty selection)](#copyLineEmptySelectionjscutLineEmptySelectionjs)
- [Create Page Numbers](#createPageNumbersjs)
-- [Create Text Parallel to Path Segment](#createTextParallelToPathSegmentjs) `New`
-- [Create Threaded Text](#createThreadedTextjs) `Update`
+- [Create Text Parallel to Path Segment](#createTextParallelToPathSegmentjs) `Update`
+- [Create Threaded Text](#createThreadedTextjs)
- [Cut Line (empty selection)](#copyLineEmptySelectionjscutLineEmptySelectionjs)
- [Delete All Left](#deleteAllLeftjsdeleteAllRightjs)
- [Delete All Right](#deleteAllLeftjsdeleteAllRightjs)
@@ -109,8 +111,8 @@ If you find a script that interests you, please download it from [![Download](ht
- [Justify Content Space Between](#justifyContentSpaceBetweenjs)
- [Move Line Down](#moveLineDownjsmoveLineUpjs)
- [Move Line Up](#moveLineDownjsmoveLineUpjs)
-- [Sort Lines](#sortLinesjs) `New`
-- [Split Text](#splitTextjs) `Update`
+- [Sort Lines](#sortLinesjs)
+- [Split Text](#splitTextjs)
- [Split Text at Cursor Position](#splitTextAtCursorPositionjs)
- [Swap Text Contents](#swapTextContentsjs)
- [Text Align Center](#textAlign_CenterjstextAlign_LeftjstextAlign_Rightjs)
@@ -186,9 +188,12 @@ It is a slightly more user-friendly improvement to Object > Path > Add Anchor Po
![Add Anchor Points](images/addAnchorPoints.png)
### Usage
-1. Select two or more anchor points with Direct Selection Tool, and run this script.
+1. Select two or more anchor points with the Direct Selection Tool, and run this script.
2. Enter the number of anchor points to add.
+> [!NOTE]
+> Anchor points for type on a path and area type are also supported.
+
### Requirements
Illustrator CS4 or higher
@@ -248,11 +253,11 @@ For example, alignInCenterOfSpace(Vertical).js:
![Align In Center Of Space](images/alignInCenterOfSpace.png)
### Usage
-Select objects, and run this script.
+Select three or more objects, and run this script.
The position of alignment depends on the reference point.
> [!NOTE]
-> The space excludes the stroke width.
+> Include or exclude the stroke width depends on the Align panel menu > Use Preview Bounds.
> Select at least three objects.
### Requirements
@@ -282,9 +287,12 @@ This script aligns objects horizontally and vertically at the same time.
> [!NOTE]
> The top row and the left-most column are the basis for alignment.
-> The units of the Distribute Spacing and the Alignment Position Tolerance depend on the ruler units.
> Compound paths, texts, linked files, and embedded link files are also supported.
+### Support units
+Point, Pixel, Pica, Inch, Feet, Yard, Millimeter, Centimeter, Meter.
+These units depend on the ruler units.
+
### Requirements
Illustrator 2021 or higher
@@ -300,7 +308,7 @@ Illustrator 2021 or higher
This script splits and arranges all open windows.
> [!TIP]
-> It has been implemented in the Application Bar since version 2022.
+> The Arrange document icon has been implemented in the Application Bar since version 2022.
![Arrange Windows](images/arrangeWindows.png)
@@ -422,13 +430,15 @@ The anchor point conversion options in the Control panel require the anchor poin
![Convert All Anchor Points To Corner](images/convertAllAnchorPointsToCorner.png)
### Usage
-Select the entire path with selection tool, and run this script.
+Select the entire path with the Selection Tool, and run this script.
+If you select anchor points with the Direct Selection Tool, a dialog will show to convert all or only selected anchor points to corner points.
+
> [!NOTE]
-> It is not necessary to select anchor points with Direct Selection Tool.
+> Anchor points for type on a path and area type are also supported.
### Requirements
-Illustrator CS or higher
+Illustrator CS4 or higher
@@ -659,13 +669,16 @@ This script creates a text parallel to a straight segment or a line connecting t
`Point Type` Select left, center, or right align.
`Area Type` Enter area width and height values.
4. Check the Flip checkbox reverses the drawing position.
-5. Check the Middle checkbox to draw in the middle of the line.
-6. Enter a value of the margin will space them from the line.
+5. Check the Middle checkbox to draw in the middle of the path segment.
+6. Enter a value of the margin will space them from the path segment.
> [!NOTE]
-> Anchor points for type on a path and area type are supported.
> Curves are not supported.
-> The units of the width, height and margin value depend on the ruler units.
+> Anchor points for type on a path and area type are also supported.
+
+### Support units
+Point, Pixel, Pica, Inch, Feet, Yard, Millimeter, Centimeter, Meter.
+These units depend on the ruler units.
### Requirements
Illustrator 2021 or higher
@@ -693,8 +706,11 @@ The vertical text is also supported.
> [!NOTE]
> The stacking order of objects and layers has no bearing on the order of concatenation.
-> When converting the path to the area type, ignore anchor points with fewer than two anchor points.
-> The units of the alignment position tolerance depend on the ruler units.
+> When converting the path to the area type, ignore anchor points with fewer than two anchor points.
+
+### Support units
+Point, Pixel, Pica, Inch, Feet, Yard, Millimeter, Centimeter, Meter.
+These units depend on the ruler units.
### Requirements
Illustrator CC or higher
@@ -925,11 +941,11 @@ For example, distributeInSpace(Vertical).js:
![Distribute In Space](images/distributeInSpace.png)
### Usage
-Select objects, and run this script.
+Select three or more objects, and run this script.
The position of alignment depends on the reference point.
> [!NOTE]
-> The space excludes the stroke width.
+> Include or exclude the stroke width depends on the Align panel menu > Use Preview Bounds.
> Select at least three objects.
### Requirements
@@ -953,7 +969,7 @@ Select 3 or 2 anchor points with Direct Selection Tool, and run this script.
> [!NOTE]
> For two anchor points, it is the diameter.
-> Anchor points for type on a path and area types are also supported.
+> Anchor points for type on a path and area type are also supported.
### Requirements
Illustrator CS or higher
@@ -965,20 +981,56 @@ Illustrator CS or higher
+# drawNormalLine.js
+[![Download Path.zip](https://img.shields.io/badge/Download-Path.zip-e60012)](https://github.com/sky-chaser-high/adobe-illustrator-scripts/releases/latest/download/Path.zip)
+This script draws normal lines (line perpendicular to a tangent) to a curve or line between two anchor points.
+
+![Draw Normal Line](images/drawNormalLine.png)
+
+### Usage
+1. Select two or more anchor points with the Direct Selection Tool, and run this script.
+2. Enter the number of normal lines to draw.
+3. Enter the length of normal line to draw.
+4. Check the Draw on Selected Anchor Points checkbox if you want to draw on the selected anchor points.
+5. Check the Flip checkbox reverses the drawing position.
+6. Check the Middle checkbox to draw in the middle of the path segment.
+7. Enter a value of the margin will space them from the path segment.
+
+> [!NOTE]
+> Anchor points for type on a path and area type are not supported.
+
+### Support units
+Point, Pixel, Pica, Inch, Feet, Yard, Millimeter, Centimeter, Meter.
+These units depend on the ruler units.
+
+### Requirements
+Illustrator CS4 or higher
+
+
+
+
+
+
+
+
# drawRectangle.js
[![Download Path.zip](https://img.shields.io/badge/Download-Path.zip-e60012)](https://github.com/sky-chaser-high/adobe-illustrator-scripts/releases/latest/download/Path.zip)
-This script draws a rectangle on a selected object.
+This script draws rectangles around selected objects.
![Draw Rectangle](images/drawRectangle.png)
### Usage
-1. Select the path objects, and run this script.
-2. Enter a margin value.
- To include stroke width, check the Include stroke width checkbox.
+1. Select any objects, and run this script.
+2. Enter a margin value.
+3. To draw a rectangle on each object in the group, check the Ignore Groups checkbox.
+4. To include stroke width, check the Use Preview Bounds checkbox.
> [!NOTE]
-> The rectangle is drawn with no fill and stroke width.
-> The units of margin value depend on the ruler units.
+> The rectangle is drawn with no fill and stroke width.
+
+### Support units
+Point, Pixel, Pica, Inch, Feet, Yard, Millimeter, Centimeter, Meter.
+These units depend on the ruler units.
### Requirements
Illustrator CS4 or higher
@@ -997,15 +1049,47 @@ This script draws shapes on anchor points.
![Draw Shape On Anchor Point](images/drawShapeOnAnchorPoint.png)
### Usage
-1. Select the path objects, and run this script.
+1. Select any path objects, and run this script.
2. Select a shape.
3. Enter a shape size.
-4. Check the Draw Handle Position checkbox if you want to draw the shapes on the handle positions.
+4. If you select anchor points with the Direct Selection Tool, choose whether to draw the shape on all anchor points or only on the selected anchor points.
+5. Check the Draw Handle Position checkbox if you want to draw the shapes on the handle positions.
+
+### Support units
+Point, Pixel, Pica, Inch, Feet, Yard, Millimeter, Centimeter, Meter.
+These units depend on the ruler units.
+
+### Requirements
+Illustrator CS4 or higher
+
+
+
+
+
+
+
+
+# drawShapeParallelToPathSegment.js
+[![Download Path.zip](https://img.shields.io/badge/Download-Path.zip-e60012)](https://github.com/sky-chaser-high/adobe-illustrator-scripts/releases/latest/download/Path.zip)
+This script draws a shape parallel to a straight segment or a line connecting two anchor points.
+
+![Draw Shape Parallel to Path Segment](images/drawShapeParallelToPathSegment.png)
+
+### Usage
+1. Select two anchor points with the Direct Selection Tool, and run this script.
+2. Select a Square, Rectangle or Ellipse.
+3. If you select the Rectangle or Ellipse, enter width and height values.
+4. Check the Flip checkbox reverses the drawing position.
+5. Check the Middle checkbox to draw in the middle of the path segment.
+6. Enter a value of the margin will space them from the path segment.
> [!NOTE]
-> If you select anchor points with Direct Selection Tool, the shape is drawn only for the selected anchor points.
-> The handle position is drawn with a stroke.
-> The units of shape size depend on the ruler units.
+> Curves are not supported.
+> Anchor points for type on a path and area type are also supported.
+
+### Support units
+Point, Pixel, Pica, Inch, Feet, Yard, Millimeter, Centimeter, Meter.
+These units depend on the ruler units.
### Requirements
Illustrator CS4 or higher
@@ -1087,14 +1171,17 @@ This script extends and shrinks handles. It also changes the angle.
![Extend Handle](images/extendHandle.png)
### Usage
-1. Select one or two anchor points with Direct Selection Tool, and run this script.
+1. Select one or two anchor points with the Direct Selection Tool, and run this script.
2. Enter a positive value in the Distance fields to extend or a negative value to shrink.
3. Enter a positive value in the Angle fields will rotate counterclockwise. Enter a negative value clockwise.
> [!NOTE]
> Handles cannot delete.
-> The angle increases or decreases based on the current value.
-> The units of distance depend on the ruler units.
+> The angle increases or decreases based on the current value.
+
+### Support units
+Point, Pixel, Pica, Inch, Feet, Yard, Millimeter, Centimeter, Meter.
+These units depend on the ruler units.
### Requirements
Illustrator CS4 or higher
@@ -1108,17 +1195,21 @@ Illustrator CS4 or higher
# extendLine.js
[![Download Path.zip](https://img.shields.io/badge/Download-Path.zip-e60012)](https://github.com/sky-chaser-high/adobe-illustrator-scripts/releases/latest/download/Path.zip)
-This script extends and shrinks a path object.
+This script extends and shrinks path segments.
![Extend Line](images/extendLine.png)
### Usage
-1. Select an anchor point with Direct Selection Tool, and run this script.
+1. Select any anchor points with the Direct Selection Tool, and run this script.
2. Enter a positive value to extend or a negative value to shrink.
> [!NOTE]
> Closed paths and curves are not supported.
-> The units of distance depend on the ruler units.
+> Anchor points for type on a path are also supported.
+
+### Support units
+Point, Pixel, Pica, Inch, Feet, Yard, Millimeter, Centimeter, Meter.
+These units depend on the ruler units.
### Requirements
Illustrator CS4 or higher
@@ -1486,7 +1577,7 @@ Select two anchor points with Direct Selection Tool, and run this script.
> Highlight the measurement points.
> The angle is based on point #1. Range: -180.0 to 180.0
> The dimension units depend on the ruler units.
-> Anchor points for type on a path and area types are also supported.
+> Anchor points for type on a path and area type are also supported.
> Due to the small font size, labels will not appear when enlarged above 15500%.
### Requirements
@@ -1655,9 +1746,12 @@ This script rearranges selected objects.
> [!NOTE]
> The object in the top-left is the basis for rearranging.
-> The units of the Spacing and the Alignment Position Tolerance depend on the ruler units.
> Compound paths, texts, linked files, and embedded link files are also supported.
+### Support units
+Point, Pixel, Pica, Inch, Feet, Yard, Millimeter, Centimeter, Meter.
+These units depend on the ruler units.
+
### Requirements
Illustrator 2021 or higher
@@ -2035,17 +2129,24 @@ Illustrator CS or higher
[![Download Path.zip](https://img.shields.io/badge/Download-Path.zip-e60012)](https://github.com/sky-chaser-high/adobe-illustrator-scripts/releases/latest/download/Path.zip)
This script shows the dimension of the anchor point between two points of the path objects.
+> [!TIP]
+> The Dimension Tool has been implemented in the Toolbar since version 2024.
+
![Show Dimensions](images/showDimensions.png)
### Usage
-Select the path objects, and run this script.
+Select any path objects, and run this script.
+If you select anchor points with the Direct Selection Tool, dimensions are displayed only at the selected. In this case, select at least two anchor points.
> [!NOTE]
> Supports curves.
> Group and color dimensions by path object.
-> The dimension units depend on the ruler units.
> In complex shapes, dimensions may be displayed overlapping each other.
+### Support units
+Point, Pixel, Pica, Inch, Feet, Yard, Millimeter, Centimeter, Meter.
+These units depend on the ruler units.
+
### Requirements
Illustrator CS6 or higher
@@ -2201,7 +2302,7 @@ Illustrator CS6 or higher
# stepAndRepeat.js
[![Download Path.zip](https://img.shields.io/badge/Download-Path.zip-e60012)](https://github.com/sky-chaser-high/adobe-illustrator-scripts/releases/latest/download/Path.zip)
-This script is equivalent to InDesign's Edit > Step and Repeat.
+This script repeatedly duplicates selected objects. It is equivalent to InDesign's Edit > Step and Repeat.
![Step and Repeat](images/stepandRepeat.png)
@@ -2211,8 +2312,9 @@ This script is equivalent to InDesign's Edit > Step and Repeat.
3. Enter the number of times to repeat.
4. Enter the offset values.
-> [!NOTE]
-> The units of the offset value depend on the ruler units.
+### Support units
+Point, Pixel, Pica, Inch, Feet, Yard, Millimeter, Centimeter, Meter.
+These units depend on the ruler units.
### Requirements
Illustrator CS4 or higher
diff --git a/README_ja.md b/README_ja.md
index 7652f4b..1e0119e 100755
--- a/README_ja.md
+++ b/README_ja.md
@@ -53,35 +53,37 @@ Adobe Illustratorのスクリプト集です。
### パス
[![Download Path.zip](https://img.shields.io/badge/Download-Path.zip-e60012?style=for-the-badge)](https://github.com/sky-chaser-high/adobe-illustrator-scripts/releases/latest/download/Path.zip)
-- [**アンカーポイントに図形を描く**](#アンカーポイントに図形を描く) drawShapeOnAnchorPoint.js
-- [**アンカーポイントの追加**](#アンカーポイントの追加) addAnchorPoints.js
-- [**オブジェクトの周囲に長方形を描く**](#オブジェクトの周囲に長方形を描く) drawRectangle.js
-- [**オブジェクトの整列**](#オブジェクトの整列) alignObjects.js
-- [**オブジェクトの並べ替え**](#オブジェクトの並べ替え) rearrangeObjects.js
+- [**アンカーポイントに図形を描く**](#アンカーポイントに図形を描く) drawShapeOnAnchorPoint.js `Update`
+- [**アンカーポイントの追加**](#アンカーポイントの追加) addAnchorPoints.js `Update`
+- [**オブジェクトの周囲に長方形を描く**](#オブジェクトの周囲に長方形を描く) drawRectangle.js `Update`
+- [**オブジェクトの整列**](#オブジェクトの整列) alignObjects.js `Update`
+- [**オブジェクトの並べ替え**](#オブジェクトの並べ替え) rearrangeObjects.js `Update`
- [**オブジェクトをシャッフル**](#オブジェクトをシャッフル) shuffleObjects.js
- [**外接円を描く**](#外接円を描く) drawCircumscribedCircle.js
- [**ガイドオブジェクトの色を削除**](#ガイドオブジェクトの色を削除) removeColorInGuideObject.js
- [**ガイドをアートボードにフィット**](#ガイドをアートボードにフィット) fitGuideInArtboard.js
- [**ガイドを移動**](#ガイドを移動) moveGuides.js
- [**ガイドを選択**](#ガイドを選択) selectGuides.js
-- [**繰り返し複製**](#繰り返し複製) stepAndRepeat.js
+- [**繰り返し複製**](#繰り返し複製) stepAndRepeat.js `Update`
- [**グリッドラインを作成**](#グリッドラインを作成) createGridLines.js
-- [**すべてのアンカーをコーナーポイントに切り替え**](#すべてのアンカーをコーナーポイントに切り替え) convertAllAnchorPointsToCorner.js
+- [**すべてのアンカーをコーナーポイントに切り替え**](#すべてのアンカーをコーナーポイントに切り替え) convertAllAnchorPointsToCorner.js `Update`
- [**選択したアンカーポイントを時計回りに移動**](#選択したアンカーポイントを時計回りに移動選択したアンカーポイントを反時計回りに移動) shiftSelectedAnchorPointsCW.js
- [**選択したアンカーポイントを反時計回りに移動**](#選択したアンカーポイントを時計回りに移動選択したアンカーポイントを反時計回りに移動) shiftSelectedAnchorPointsCCW.js
- [**選択したアンカーポイントを時計回りに増やす**](#選択したアンカーポイントを時計回りに増やす選択したアンカーポイントを反時計回りに増やす) increaseSelectedAnchorPointsCW.js
- [**選択したアンカーポイントを反時計回りに増やす**](#選択したアンカーポイントを時計回りに増やす選択したアンカーポイントを反時計回りに増やす) increaseSelectedAnchorPointsCCW.js
- [**選択したアンカーポイントを時計回りに減らす**](#選択したアンカーポイントを時計回りに減らす選択したアンカーポイントを反時計回りに減らす) decreaseSelectedAnchorPointsCW.js
- [**選択したアンカーポイントを反時計回りに減らす**](#選択したアンカーポイントを時計回りに減らす選択したアンカーポイントを反時計回りに減らす) decreaseSelectedAnchorPointsCCW.js
-- [**ハンドルを伸縮**](#ハンドルを伸縮) extendHandle.js
-- [**パスの寸法を表示**](#パスの寸法を表示) showDimensions.js
-- [**パスを伸縮**](#パスを伸縮) extendLine.js
+- [**直線に平行な図形を描く**](#直線に平行な図形を描く) drawShapeParallelToPathSegment.js `New`
+- [**ハンドルを伸縮**](#ハンドルを伸縮) extendHandle.js `Update`
+- [**パスの寸法を表示**](#パスの寸法を表示) showDimensions.js `Update`
+- [**パスを伸縮**](#パスを伸縮) extendLine.js `Update`
- [**パスを閉じる**](#パスを閉じる) closePath.js
- [**パスを分解**](#パスを分解) disjoinPath.js
-- [**余白の垂直方向中央に整列**](#余白の垂直方向中央に整列余白の水平方向中央に整列) alignInCenterOfSpace(Vertical).js
-- [**余白の水平方向中央に整列**](#余白の垂直方向中央に整列余白の水平方向中央に整列) alignInCenterOfSpace(Horizontal).js
-- [**余白の垂直方向に分布**](#余白の垂直方向に分布余白の水平方向に分布) distributeInSpace(Vertical).js
-- [**余白の水平方向に分布**](#余白の垂直方向に分布余白の水平方向に分布) distributeInSpace(Horizotal).js
+- [**法線を描く**](#法線を描く) drawNormalLine.js `New`
+- [**余白の垂直方向中央に整列**](#余白の垂直方向中央に整列余白の水平方向中央に整列) alignInCenterOfSpace(Vertical).js `Update`
+- [**余白の水平方向中央に整列**](#余白の垂直方向中央に整列余白の水平方向中央に整列) alignInCenterOfSpace(Horizontal).js `Update`
+- [**余白の垂直方向に分布**](#余白の垂直方向に分布余白の水平方向に分布) distributeInSpace(Vertical).js `Update`
+- [**余白の水平方向に分布**](#余白の垂直方向に分布余白の水平方向に分布) distributeInSpace(Horizotal).js `Update`
### テキスト
[![Download Text.zip](https://img.shields.io/badge/Download-Text.zip-e60012?style=for-the-badge)](https://github.com/sky-chaser-high/adobe-illustrator-scripts/releases/latest/download/Text.zip)
@@ -91,7 +93,7 @@ Adobe Illustratorのスクリプト集です。
- [**カーソルを次のテキストへ移動**](#カーソルを次のテキストへ移動カーソルを前のテキストへ移動) goToNextText.js
- [**カーソルを前のテキストへ移動**](#カーソルを次のテキストへ移動カーソルを前のテキストへ移動) goToPreviousText.js
- [**行に移動**](#行に移動) goToLine.js
-- [**行の並べ替え**](#行の並べ替え) sortLines.js `New`
+- [**行の並べ替え**](#行の並べ替え) sortLines.js
- [**行末のスペースを削除**](#行末のスペースを削除) deleteTrailingSpaces.js
- [**行を上へ移動**](#行を上へ移動行を下へ移動) moveLineUp.js
- [**行を下へ移動**](#行を上へ移動行を下へ移動) moveLineDown.js
@@ -99,11 +101,11 @@ Adobe Illustratorのスクリプト集です。
- [**行を下へコピー**](#行を上へコピー行を下へコピー) copyLineDown.js
- [**行を上に挿入**](#行を上に挿入行を下に挿入) insertLineAbove.js
- [**行を下に挿入**](#行を上に挿入行を下に挿入) insertLineBelow.js
-- [**数字をカンマで区切る**](#数字をカンマで区切る) addNumericSeparators.js `Update`
-- [**スレッドテキストを作成**](#スレッドテキストを作成) createThreadedText.js `Update`
+- [**数字をカンマで区切る**](#数字をカンマで区切る) addNumericSeparators.js
+- [**スレッドテキストを作成**](#スレッドテキストを作成) createThreadedText.js
- [**選択なしでカット**](#選択なしでカット選択なしでコピー) cutLine(emptySelection).js
- [**選択なしでコピー**](#選択なしでカット選択なしでコピー) copyLine(emptySelection).js
-- [**直線に平行なテキストを作成**](#直線に平行なテキストを作成) createTextParallelToPathSegment.js `New`
+- [**直線に平行なテキストを作成**](#直線に平行なテキストを作成) createTextParallelToPathSegment.js `Update`
- [**テキスト中央揃え**](#テキスト中央揃えテキスト左揃えテキスト右揃え) textAlign_Center.js
- [**テキスト左揃え**](#テキスト中央揃えテキスト左揃えテキスト右揃え) textAlign_Left.js
- [**テキスト右揃え**](#テキスト中央揃えテキスト左揃えテキスト右揃え) textAlign_Right.js
@@ -113,7 +115,7 @@ Adobe Illustratorのスクリプト集です。
- [**文字列を括弧で囲む**](#文字列を括弧で囲む) encloseWordInParentheses.js
- [**文字列をカーソルの位置で分割**](#文字列をカーソルの位置で分割) splitTextAtCursorPosition.js
- [**文字列を交換**](#文字列を交換) swapTextContents.js
-- [**文字列を分割**](#文字列を分割) splitText.js `Update`
+- [**文字列を分割**](#文字列を分割) splitText.js
### ユーティリティ
[![Download Utility.zip](https://img.shields.io/badge/Download-Utility.zip-e60012?style=for-the-badge)](https://github.com/sky-chaser-high/adobe-illustrator-scripts/releases/latest/download/Utility.zip)
@@ -204,6 +206,9 @@ MITライセンスのもとで公開しています。
1. ダイレクト選択ツールで2点以上のアンカーポイントを選択してスクリプトを実行します。
2. 追加したい個数を入力します。
+> [!NOTE]
+> パス上文字とエリア内文字のアンカーポイントにも対応しています。
+
#### 動作条件
Illustrator CS4以降
@@ -266,11 +271,11 @@ Illustrator CS以降
![Align In Center Of Space](images/alignInCenterOfSpace.png)
#### 使用方法
-オブジェクトを選択してスクリプトを実行します。
-整列の位置は、基準点により変わります。
+3つ以上のオブジェクトを選択してスクリプトを実行します。
+整列の位置は、基準点により変化します。
> [!NOTE]
-> 余白は線幅を含みません。
+> 線幅を含めるか含めないかは、「整列パネルメニュー > プレビュー境界を使用」によります。
> オブジェクトは3つ以上選択してください。
#### 動作条件
@@ -303,9 +308,12 @@ Illustrator CS3以降
> [!NOTE]
> 最上段の行と左端の列が整列の基準になります。
-> [等間隔に分布]と[整列位置の許容誤差]の単位は、ルーラー単位により変わります。
> 複合パス、テキスト、リンク画像、埋め込み画像にも対応しています。
+#### 対応する単位
+ポイント、ピクセル、パイカ、インチ、フィート、ヤード、ミリメートル、センチメートル、メートル。
+使用する単位は、定規の単位によります。
+
#### 動作条件
Illustrator 2021以降
@@ -454,13 +462,16 @@ Illustrator CS4以降
![Convert All Anchor Points To Corner](images/convertAllAnchorPointsToCorner.png)
#### 使用方法
-選択ツールでパスオブジェクト全体を選択してスクリプトを実行します。
+選択ツールでパスオブジェクト全体を選択してスクリプトを実行します。
+ダイレクト選択ツールでアンカーポイントを選択した場合は、すべてまたは選択したアンカーポイントのみをコーナーポイントに切り替えるダイアログを表示します。
+
> [!NOTE]
-> ダイレクト選択ツールでアンカーポイントを選択する必要はありません。
+> パス上文字とエリア内文字のアンカーポイントにも対応しています。
+> Illustrator日本語版を使用している場合は、UIは日本語で表示します。
#### 動作条件
-Illustrator CS以降
+Illustrator CS4以降
@@ -707,13 +718,16 @@ Illustrator CS4以降
`ポイント文字` 左揃え、中央揃え、右揃えを選択します。
`エリア内文字` テキストエリアの幅と高さを入力します。
4. [反転]にチェックを付けるとテキストの表示位置が反転します。
-5. [中間]にチェックを付けると直線の中央に表示します。
-6. 間隔の値を入力すると直線から間隔をあけます。
+5. [中間]にチェックを付けるとパスセグメントの中央に描きます。
+6. 間隔の値を入力するとパスセグメントから間隔をあけます。
> [!NOTE]
-> パス上文字とエリア内文字のアンカーポイントに対応しています。
> 曲線には対応していません。
-> エリア内文字の幅と高さ、間隔の値の単位はルーラー単位により変わります。
+> パス上文字とエリア内文字のアンカーポイントにも対応しています。
+
+#### 対応する単位
+ポイント、ピクセル、パイカ、インチ、フィート、ヤード、ミリメートル、センチメートル、メートル。
+使用する単位は、定規の単位によります。
#### 動作条件
Illustrator 2021以降
@@ -744,8 +758,11 @@ Illustrator 2021以降
> [!NOTE]
> オブジェクトやレイヤーの重ね順は、連結する順番には関係ありません。
-> パスをエリア内文字に変換する場合、アンカーポイントの数が2点以下のパスは変換しません。
-> 整列位置の許容誤差の単位はルーラー単位により変わります。
+> パスをエリア内文字に変換する場合、アンカーポイントの数が2点以下のパスは変換しません。
+
+#### 対応する単位
+ポイント、ピクセル、パイカ、インチ、フィート、ヤード、ミリメートル、センチメートル、メートル。
+使用する単位は、定規の単位によります。
#### 動作条件
Illustrator CC以降
@@ -988,11 +1005,11 @@ Illustrator CS以降
![Distribute In Space](images/distributeInSpace.png)
#### 使用方法
-オブジェクトを選択してスクリプトを実行します。
-分布の位置は、基準点により変わります。
+3つ以上のオブジェクトを選択してスクリプトを実行します。
+分布の位置は、基準点により変化します。
> [!NOTE]
-> 余白は線幅を含みません。
+> 線幅を含めるか含めないかは、「整列パネルメニュー > プレビュー境界を使用」によります。
> オブジェクトは3つ以上選択してください。
#### 動作条件
@@ -1017,7 +1034,7 @@ Illustrator CS3以降
> [!NOTE]
> アンカーポイント2点の場合は、直径になります。
-> パス上文字、エリア内文字のアンカーポイントにも対応しています。
+> パス上文字とエリア内文字のアンカーポイントにも対応しています。
#### 動作条件
Illustrator CS以降
@@ -1029,6 +1046,41 @@ Illustrator CS以降
+## 法線を描く
+[![Download Path.zip](https://img.shields.io/badge/Download-Path.zip-e60012)](https://github.com/sky-chaser-high/adobe-illustrator-scripts/releases/latest/download/Path.zip)
+### drawNormalLine.js
+2点のアンカーポイント間の曲線または直線に対して法線(接線に垂直な線)を描きます。
+
+![Draw Normal Line](images/drawNormalLine.png)
+> [!NOTE]
+> Illustrator日本語版を使用している場合は、UIは日本語で表示します。
+
+#### 使用方法
+1. ダイレクト選択ツールで2点以上のアンカーポイントを選択してスクリプトを実行します。
+2. 法線の数を入力します。
+3. 法線の長さを入力します。
+4. 選択したアンカーポイントにも描く場合は、[選択アンカーポイントにも描く]にチェックを付けます。
+5. [反転]にチェックを付けると法線の表示位置が反転します。
+6. [中間]にチェックを付けるとパスセグメントの中央に描きます。
+7. 距離の値を入力するとパスセグメントから間隔をあけます。
+
+> [!NOTE]
+> パス上文字とエリア内文字のアンカーポイントには対応していません。
+
+#### 対応する単位
+ポイント、ピクセル、パイカ、インチ、フィート、ヤード、ミリメートル、センチメートル、メートル。
+使用する単位は、定規の単位によります。
+
+#### 動作条件
+Illustrator CS4以降
+
+
+
+
+
+
+
+
## オブジェクトの周囲に長方形を描く
[![Download Path.zip](https://img.shields.io/badge/Download-Path.zip-e60012)](https://github.com/sky-chaser-high/adobe-illustrator-scripts/releases/latest/download/Path.zip)
### drawRectangle.js
@@ -1040,12 +1092,16 @@ Illustrator CS以降
#### 使用方法
1. パスオブジェクトを選択してスクリプトを実行します。
-2. マージンを入力します。
- 線幅を含める場合は、[線幅を含む]にチェックを付けます。
+2. マージンの値を入力します。
+3. グループ内のそれぞれのオブジェクトに長方形を描く場合は、[グループを無視]にチェックを付けます。
+4. 線幅を含める場合は、[プレビュー境界を使用]にチェックを付けます。
> [!NOTE]
-> 塗りと線幅なしの長方形を描きます。
-> マージンの単位はルーラー単位により変わります。
+> 塗りと線幅なしの長方形を描きます。
+
+#### 対応する単位
+ポイント、ピクセル、パイカ、インチ、フィート、ヤード、ミリメートル、センチメートル、メートル。
+使用する単位は、定規の単位によります。
#### 動作条件
Illustrator CS4以降
@@ -1060,7 +1116,7 @@ Illustrator CS4以降
## アンカーポイントに図形を描く
[![Download Path.zip](https://img.shields.io/badge/Download-Path.zip-e60012)](https://github.com/sky-chaser-high/adobe-illustrator-scripts/releases/latest/download/Path.zip)
### drawShapeOnAnchorPoint.js
-アンカーポイントの位置に図形を描きます。
+アンカーポイントとハンドルの位置に図形を描きます。
![Draw Shape On Anchor Point](images/drawShapeOnAnchorPoint.png)
> [!NOTE]
@@ -1070,12 +1126,47 @@ Illustrator CS4以降
1. パスオブジェクトを選択してスクリプトを実行します。
2. 描く図形を選択します。
3. 図形のサイズを入力します。
-4. ハンドルの位置を描きたい場合は、[ハンドル位置も描く]にチェックを付けます。
+4. ダイレクト選択ツールでアンカーポイントを選択した場合は、すべてのアンカーポイントに図形を描くか選択したアンカーポイントのみに描くかを選択します。
+5. ハンドルの位置を描きたい場合は、[ハンドル位置も描く]にチェックを付けます。
+
+#### 対応する単位
+ポイント、ピクセル、パイカ、インチ、フィート、ヤード、ミリメートル、センチメートル、メートル。
+使用する単位は、定規の単位によります。
+
+#### 動作条件
+Illustrator CS4以降
+
+
+
+
+
+
+
+
+## 直線に平行な図形を描く
+[![Download Path.zip](https://img.shields.io/badge/Download-Path.zip-e60012)](https://github.com/sky-chaser-high/adobe-illustrator-scripts/releases/latest/download/Path.zip)
+### drawShapeParallelToPathSegment.js
+直線セグメント、または2点のアンカーポイントを結ぶ直線に平行な図形を描きます。
+
+![Draw Shape Parallel to Path Segment](images/drawShapeParallelToPathSegment.png)
+> [!NOTE]
+> Illustrator日本語版を使用している場合は、UIは日本語で表示します。
+
+#### 使用方法
+1. ダイレクト選択ツールで2点のアンカーポイントを選択してスクリプトを実行します。
+2. 正方形、長方形、または楕円を選択します。
+3. 長方形または楕円を選択した場合は、幅と高さの値を入力します。
+4. [反転]にチェックを付けると図形の表示位置が反転します。
+5. [中間]にチェックを付けるとパスセグメントの中央に描きます。
+6. 間隔の値を入力するとパスセグメントから間隔をあけます。
> [!NOTE]
-> ダイレクト選択ツールでアンカーポイントを選択すると、選択した箇所にだけ図形を描きます。
-> ハンドル位置は線で描きます。
-> 図形サイズの単位はルーラー単位により変わります。
+> 曲線には対応していません。
+> パス上文字とエリア内文字のアンカーポイントにも対応しています。
+
+#### 対応する単位
+ポイント、ピクセル、パイカ、インチ、フィート、ヤード、ミリメートル、センチメートル、メートル。
+使用する単位は、定規の単位によります。
#### 動作条件
Illustrator CS4以降
@@ -1171,8 +1262,11 @@ Illustrator CS以降
> [!NOTE]
> ハンドルは削除できません。
-> 角度は現在の値を基準にして増減します。
-> 距離の単位はルーラー単位により変わります。
+> 角度は現在の値を基準にして増減します。
+
+#### 対応する単位
+ポイント、ピクセル、パイカ、インチ、フィート、ヤード、ミリメートル、センチメートル、メートル。
+使用する単位は、定規の単位によります。
#### 動作条件
Illustrator CS4以降
@@ -1187,7 +1281,7 @@ Illustrator CS4以降
## パスを伸縮
[![Download Path.zip](https://img.shields.io/badge/Download-Path.zip-e60012)](https://github.com/sky-chaser-high/adobe-illustrator-scripts/releases/latest/download/Path.zip)
### extendLine.js
-パスオブジェクトを伸縮します。
+選択しているパスセグメントを伸縮します。
![Extend Line](images/extendLine.png)
> [!NOTE]
@@ -1199,7 +1293,11 @@ Illustrator CS4以降
> [!NOTE]
> 閉じたパスと曲線には対応していません。
-> 距離の単位はルーラー単位により変わります。
+> パス上文字のアンカーポイントにも対応しています。
+
+#### 対応する単位
+ポイント、ピクセル、パイカ、インチ、フィート、ヤード、ミリメートル、センチメートル、メートル。
+使用する単位は、定規の単位によります。
#### 動作条件
Illustrator CS4以降
@@ -1591,7 +1689,7 @@ Illustrator CS4以降
> 測定箇所をハイライトします。
> 角度はポイント#1を基準にします。
> 寸法の単位はルーラー単位により変わります。
-> パス上文字、エリア内文字のアンカーポイントにも対応しています。
+> パス上文字とエリア内文字のアンカーポイントにも対応しています。
> フォントサイズが小さくなりすぎるため、15500%以上に拡大表示するとラベルが表示されません。
#### 動作条件
@@ -1773,9 +1871,12 @@ Illustrator CS4以降
> [!NOTE]
> 左上のオブジェクトが並べ替えの基準になります。
-> [間隔]と[整列位置の許容誤差]の単位は、ルーラー単位により変わります。
> 複合パス、テキスト、リンク画像、埋め込み画像にも対応しています。
+#### 対応する単位
+ポイント、ピクセル、パイカ、インチ、フィート、ヤード、ミリメートル、センチメートル、メートル。
+使用する単位は、定規の単位によります。
+
#### 動作条件
Illustrator 2021以降
@@ -2178,17 +2279,24 @@ Illustrator CS以降
### showDimensions.js
パスオブジェクトの2点間のアンカーポイントの寸法を表示します。
+> [!TIP]
+> バージョン2024から寸法ツールがツールバーに実装されています。
+
![Show Dimensions](images/showDimensions.png)
#### 使用方法
-パスオブジェクトを選択してスクリプトを実行します。
+パスオブジェクトを選択してスクリプトを実行します。
+ダイレクト選択ツールでアンカーポイントを選択した場合は、選択した箇所のみに表示します。この場合は、2点以上のアンカーポイントを選択してください。
> [!NOTE]
> 曲線に対応しています。
> パスオブジェクトごとに寸法をグループ化し色を付けます。
-> 寸法の単位はルーラー単位により変わります。
> オブジェクトが複雑な形状や小さい場合、寸法が重なって表示されることがあります。
+#### 対応する単位
+ポイント、ピクセル、パイカ、インチ、フィート、ヤード、ミリメートル、センチメートル、メートル。
+使用する単位は、定規の単位によります。
+
#### 動作条件
Illustrator CS6以降
@@ -2357,7 +2465,7 @@ Illustrator CS6以降
## 繰り返し複製
[![Download Path.zip](https://img.shields.io/badge/Download-Path.zip-e60012)](https://github.com/sky-chaser-high/adobe-illustrator-scripts/releases/latest/download/Path.zip)
### stepAndRepeat.js
-InDesignの「編集 > 繰り返し複製」に相当します。
+選択したオブジェクトを繰り返し複製します。InDesignの「編集 > 繰り返し複製」に相当します。
![Step and Repeat](images/stepandRepeat.png)
> [!NOTE]
@@ -2365,13 +2473,14 @@ InDesignの「編集 > 繰り返し複製」に相当します。
#### 使用方法
1. オブジェクトを選択してスクリプトを実行します。
-2. グリッド状にしたい場合は、[グリッドとして作成]にチェックを付けてください。
+2. グリッド状にしたい場合は、[グリッドとして作成]にチェックを付けます。
3. 繰り返しの場合はカウントに繰り返す回数を入力します。
グリッドの場合は行・段数にそれぞれ繰り返す回数を入力します。
4. オフセット値(オブジェクトの間隔)を入力します。
-> [!NOTE]
-> オフセット値の単位は、ルーラー単位により切り替わります。
+#### 対応する単位
+ポイント、ピクセル、パイカ、インチ、フィート、ヤード、ミリメートル、センチメートル、メートル。
+使用する単位は、定規の単位によります。
#### 動作条件
Illustrator CS4以降
diff --git a/images/ConvertToCornerDialog.png b/images/ConvertToCornerDialog.png
new file mode 100644
index 0000000..eee36c2
Binary files /dev/null and b/images/ConvertToCornerDialog.png differ
diff --git a/images/addAnchorPoints.png b/images/addAnchorPoints.png
index 9b24b74..ad79dde 100644
Binary files a/images/addAnchorPoints.png and b/images/addAnchorPoints.png differ
diff --git a/images/alignInCenterOfSpace.png b/images/alignInCenterOfSpace.png
index 621be4c..5e7f3ec 100644
Binary files a/images/alignInCenterOfSpace.png and b/images/alignInCenterOfSpace.png differ
diff --git a/images/alignObjects.png b/images/alignObjects.png
index 925e830..237f9ef 100644
Binary files a/images/alignObjects.png and b/images/alignObjects.png differ
diff --git a/images/closePath.png b/images/closePath.png
index 395b88a..0683397 100644
Binary files a/images/closePath.png and b/images/closePath.png differ
diff --git a/images/convertAllAnchorPointsToCorner.png b/images/convertAllAnchorPointsToCorner.png
index 1826b4e..f032189 100644
Binary files a/images/convertAllAnchorPointsToCorner.png and b/images/convertAllAnchorPointsToCorner.png differ
diff --git a/images/createGridLines.png b/images/createGridLines.png
index 588bcde..59c2061 100644
Binary files a/images/createGridLines.png and b/images/createGridLines.png differ
diff --git a/images/createTextParallelToPathSegment.png b/images/createTextParallelToPathSegment.png
index 98cc8ef..244f6b6 100644
Binary files a/images/createTextParallelToPathSegment.png and b/images/createTextParallelToPathSegment.png differ
diff --git a/images/decreaseSelectedAnchorPoints.png b/images/decreaseSelectedAnchorPoints.png
index b7a4cee..1a0e2ad 100644
Binary files a/images/decreaseSelectedAnchorPoints.png and b/images/decreaseSelectedAnchorPoints.png differ
diff --git a/images/disjoinPath.png b/images/disjoinPath.png
index 5035224..9c26cf7 100644
Binary files a/images/disjoinPath.png and b/images/disjoinPath.png differ
diff --git a/images/distributeInSpace.png b/images/distributeInSpace.png
index ceb7804..be654d9 100644
Binary files a/images/distributeInSpace.png and b/images/distributeInSpace.png differ
diff --git a/images/drawCircumscribedCircle.png b/images/drawCircumscribedCircle.png
index e129386..f43c35a 100644
Binary files a/images/drawCircumscribedCircle.png and b/images/drawCircumscribedCircle.png differ
diff --git a/images/drawNormalLine.png b/images/drawNormalLine.png
new file mode 100644
index 0000000..bf94bd1
Binary files /dev/null and b/images/drawNormalLine.png differ
diff --git a/images/drawRectangle.png b/images/drawRectangle.png
index d522bf8..414ae90 100644
Binary files a/images/drawRectangle.png and b/images/drawRectangle.png differ
diff --git a/images/drawShapeOnAnchorPoint.png b/images/drawShapeOnAnchorPoint.png
index 2a6e3cc..aee9a74 100644
Binary files a/images/drawShapeOnAnchorPoint.png and b/images/drawShapeOnAnchorPoint.png differ
diff --git a/images/drawShapeParallelToPathSegment.png b/images/drawShapeParallelToPathSegment.png
new file mode 100644
index 0000000..f4e41ff
Binary files /dev/null and b/images/drawShapeParallelToPathSegment.png differ
diff --git a/images/extendHandle.png b/images/extendHandle.png
index 2e5bb0e..4ef5494 100644
Binary files a/images/extendHandle.png and b/images/extendHandle.png differ
diff --git a/images/extendLine.png b/images/extendLine.png
index 7fcd15f..56b9fb2 100644
Binary files a/images/extendLine.png and b/images/extendLine.png differ
diff --git a/images/fitGuideInArtboard.png b/images/fitGuideInArtboard.png
index b4f3f52..3aeeb27 100644
Binary files a/images/fitGuideInArtboard.png and b/images/fitGuideInArtboard.png differ
diff --git a/images/increaseSelectedAnchorPoints.png b/images/increaseSelectedAnchorPoints.png
index 7d61551..e9b98aa 100644
Binary files a/images/increaseSelectedAnchorPoints.png and b/images/increaseSelectedAnchorPoints.png differ
diff --git a/images/moveGuides.png b/images/moveGuides.png
index f8a99c4..fe67068 100644
Binary files a/images/moveGuides.png and b/images/moveGuides.png differ
diff --git a/images/rearrangeObjects.png b/images/rearrangeObjects.png
index 90d3222..0d31b92 100644
Binary files a/images/rearrangeObjects.png and b/images/rearrangeObjects.png differ
diff --git a/images/removeColorInGuideObject.png b/images/removeColorInGuideObject.png
index 8c94be5..b2befc1 100644
Binary files a/images/removeColorInGuideObject.png and b/images/removeColorInGuideObject.png differ
diff --git a/images/shiftSelectedAnchorPoints.png b/images/shiftSelectedAnchorPoints.png
index a14dbaf..34aa2aa 100644
Binary files a/images/shiftSelectedAnchorPoints.png and b/images/shiftSelectedAnchorPoints.png differ
diff --git a/images/shuffleObjects.png b/images/shuffleObjects.png
index 54e33b7..c8b3acd 100644
Binary files a/images/shuffleObjects.png and b/images/shuffleObjects.png differ
diff --git a/images/sortLines.png b/images/sortLines.png
index c14bce5..bf5316c 100644
Binary files a/images/sortLines.png and b/images/sortLines.png differ
diff --git a/images/stepandRepeat.png b/images/stepandRepeat.png
index a1fdfe2..8fbc989 100644
Binary files a/images/stepandRepeat.png and b/images/stepandRepeat.png differ
diff --git a/scripts/addAnchorPoints.js b/scripts/addAnchorPoints.js
index 89837fb..eb9ea5d 100755
--- a/scripts/addAnchorPoints.js
+++ b/scripts/addAnchorPoints.js
@@ -6,10 +6,11 @@
It is a slightly more user-friendly improvement to Object > Path > Add Anchor Points.
Usage
- 1. Select two or more anchor points with Direct Selection Tool, run this script from File > Scripts > Other Script...
+ 1. Select two or more anchor points with the Direct Selection Tool, run this script from File > Scripts > Other Script...
2. Enter the number of anchor points to add.
Notes
+ Anchor points for type on a path and area type are also supported.
In rare cases, the script may not work if you continue to use it.
In this case, restart Illustrator and try again.
@@ -17,7 +18,7 @@
Illustrator CS4 or higher
Version
- 1.0.0
+ 1.1.0
Homepage
github.com/sky-chaser-high/adobe-illustrator-scripts
@@ -28,24 +29,25 @@
=============================================================================================================================================== */
(function() {
- if (app.documents.length > 0) main();
+ if (app.documents.length && isValidVersion()) main();
})();
function main() {
var items = app.activeDocument.selection;
var shapes = getPathItems(items);
+ var texts = getTextPathItems();
+ shapes = shapes.concat(texts);
if (!shapes.length) return;
var dialog = showDialog();
dialog.ok.onClick = function() {
- var count = parseInt(dialog.count.text);
- if (count < 1 || isNaN(count)) return dialog.close();
+ var count = parseInt(getValue(dialog.count.text));
+ if (!count) return dialog.close();
for (var i = 0; i < shapes.length; i++) {
var shape = shapes[i];
- if (!hasSelectedAnchorPoints(shape)) continue;
addAnchorPoints(shape, count);
}
dialog.close();
@@ -56,74 +58,50 @@ function main() {
function addAnchorPoints(shape, count) {
- var points = getAllAnchorPoints(shape);
- var entirePoints = getEntirePoints(shape, points, count);
-
- shape.setEntirePath(entirePoints.anchor);
- for (var i = 0; i < entirePoints.anchor.length; i++) {
+ var points = getEntirePoints(shape, count);
+ shape.setEntirePath(points.anchor);
+ for (var i = 0; i < points.anchor.length; i++) {
var handle = shape.pathPoints[i];
- handle.leftDirection = entirePoints.left[i];
- handle.rightDirection = entirePoints.right[i];
+ handle.leftDirection = points.left[i];
+ handle.rightDirection = points.right[i];
}
shape.selected = true;
}
-function getAllAnchorPoints(item) {
- var points = {
- anchor: [],
- left: [],
- right: []
- };
- for (var i = 0; i < item.pathPoints.length; i++) {
- var point = item.pathPoints[i];
- points.anchor.push([
- point.anchor[0],
- point.anchor[1]
- ]);
- points.left.push([
- point.leftDirection[0],
- point.leftDirection[1]
- ]);
- points.right.push([
- point.rightDirection[0],
- point.rightDirection[1]
- ]);
- }
- return points;
-}
-
-
-function getEntirePoints(item, points, count) {
- for (var i = 0, index = 0; i < item.pathPoints.length; i++) {
+function getEntirePoints(item, count) {
+ var points = getCurrentPoints(item);
+ var start = 0;
+ var last = item.pathPoints.length - 1;
+ for (var i = start, index = start; i < item.pathPoints.length; i++) {
if (!isSelected(item, i)) continue;
var p1 = item.pathPoints[i];
- var last = item.pathPoints.length - 1;
- var next = (i < last) ? i + 1 : 0;
+ var next = (i < last) ? i + 1 : start;
var p2 = item.pathPoints[next];
- var position, insertPoint;
- var times = count * index;
+ var additionalPoints, insertPoint;
+ var steps = index * count;
- if (hasCurve(p1, p2)) {
- position = getCurvedPositions(p1, p2, count);
- var start = 0;
- var end = position.anchor.length - 1;
- position.left[start] = points.left[i + times];
- position.right[end] = points.right[next + times];
+ if (isCurve(p1, p2)) {
+ additionalPoints = getCurvedPositions(p1, p2, count);
+ var end = additionalPoints.anchor.length - 1;
+ additionalPoints.left[start] = points.left[i + steps];
+ additionalPoints.right[end] = points.right[next + steps];
if (i == last) {
- points.left[start] = position.left[end];
- position.anchor.pop();
+ points.left[start] = additionalPoints.left[end];
+ additionalPoints.anchor.pop();
}
- insertPoint = [i + times, 2];
+ insertPoint = [i + steps, 2];
}
else {
- position = getLinearPositions(p1, p2, count);
- insertPoint = [i + 1 + times, 0];
+ additionalPoints = getLinearPositions(p1, p2, count);
+ insertPoint = [i + steps + 1, 0];
}
- points = concatenate(points, position, insertPoint);
+ points.anchor = concatenate(points.anchor, additionalPoints.anchor, insertPoint);
+ points.left = concatenate(points.left, additionalPoints.left, insertPoint);
+ points.right = concatenate(points.right, additionalPoints.right, insertPoint);
index++;
}
return points;
@@ -133,49 +111,42 @@ function getEntirePoints(item, points, count) {
// Insert an array into an array to make a single array.
// https://stackoverflow.com/questions/1348178/a-better-way-to-splice-an-array-into-an-array-in-javascript
// Array.prototype.splice.apply(array1, [start, deleteCount].concat(array2));
-function concatenate(points, position, insertPoint) {
- Array.prototype.splice.apply(points.anchor, insertPoint.concat(position.anchor));
- Array.prototype.splice.apply(points.left, insertPoint.concat(position.left));
- Array.prototype.splice.apply(points.right, insertPoint.concat(position.right));
- return points;
+function concatenate(array1, array2, insertPoint) {
+ Array.prototype.splice.apply(array1, insertPoint.concat(array2));
+ return array1;
}
-function isSelected(item, index) {
- var ANCHOR = PathPointSelection.ANCHORPOINT;
-
- var p1 = item.pathPoints[index];
- if (p1.selected != ANCHOR) return false;
-
- var last = item.pathPoints.length - 1;
- if (index == last && !item.closed) return false;
-
- var next = (index < last) ? index + 1 : 0;
- var p2 = item.pathPoints[next];
- if (p2.selected != ANCHOR) return false;
- return true;
+function getCurrentPoints(item) {
+ var points = {
+ anchor: [], left: [], right: []
+ };
+ for (var i = 0; i < item.pathPoints.length; i++) {
+ var point = item.pathPoints[i];
+ points.anchor.push(point.anchor);
+ points.left.push(point.leftDirection);
+ points.right.push(point.rightDirection);
+ }
+ return points;
}
function getLinearPositions(p1, p2, count) {
- var position = {
- anchor: [],
- left: [],
- right: []
- };
+ var points = count + 1;
var x1 = p1.anchor[0];
var y1 = p1.anchor[1];
var x2 = p2.anchor[0];
var y2 = p2.anchor[1];
- var width = x2 - x1;
- var height = y2 - y1;
- var points = count + 1;
- var x = width / points;
- var y = height / points;
+ var dx = (x2 - x1) / points;
+ var dy = (y2 - y1) / points;
+
+ var position = {
+ anchor: [], left: [], right: []
+ };
for (var i = 1; i < points; i++) {
position.anchor.push([
- x1 + (x * i),
- y1 + (y * i)
+ x1 + (dx * i),
+ y1 + (dy * i)
]);
}
position.left = position.anchor;
@@ -319,44 +290,43 @@ function mult(a, t) {
}
-function hasCurve(p1, p2) {
+function hasHandle(anchor, handle) {
+ var x = 0;
+ var y = 1;
+ return anchor[x] != handle[x] || anchor[y] != handle[y];
+}
+
+
+function isCurve(p1, p2) {
var right = hasHandle(p1.anchor, p1.rightDirection);
var left = hasHandle(p2.anchor, p2.leftDirection);
- if (left || right) return true;
- return false;
+ return left || right;
}
-function hasHandle(anchor, handle) {
- var a = {
- x: anchor[0],
- y: anchor[1]
- };
- var h = {
- x: handle[0],
- y: handle[1]
- };
- if (a.x == h.x && a.y == h.y) return false;
- return true;
+function hasSelectedAnchorPoints(item) {
+ var points = item.pathPoints;
+ for (var i = 0; i < points.length; i++) {
+ if (isSelected(item, i)) return true;
+ }
+ return false;
}
-function hasSelectedAnchorPoints(item) {
+function isSelected(item, index) {
var ANCHOR = PathPointSelection.ANCHORPOINT;
- for (var i = 0; i < item.pathPoints.length; i++) {
- var p1 = item.pathPoints[i];
- if (p1.selected != ANCHOR) continue;
+ var points = item.pathPoints;
- var last = item.pathPoints.length - 1;
- if (i == last && !item.closed) continue;
+ var p1 = points[index];
+ if (p1.selected != ANCHOR) return false;
- var index = (i < last) ? i + 1 : 0;
- var p2 = item.pathPoints[index];
- if (p2.selected != ANCHOR) continue;
+ var last = points.length - 1;
+ if (index == last && !item.closed) return false;
- return true;
- }
- return false;
+ var next = (index < last) ? index + 1 : 0;
+ var p2 = points[next];
+ if (p2.selected != ANCHOR) return false;
+ return true;
}
@@ -364,7 +334,7 @@ function getPathItems(items) {
var shapes = [];
for (var i = 0; i < items.length; i++) {
var item = items[i];
- if (item.typename == 'PathItem') {
+ if (item.typename == 'PathItem' && hasSelectedAnchorPoints(item)) {
shapes.push(item);
}
if (item.typename == 'GroupItem') {
@@ -378,13 +348,46 @@ function getPathItems(items) {
}
+function getTextPathItems() {
+ var items = [];
+ var texts = app.activeDocument.textFrames;
+ for (var i = 0; i < texts.length; i++) {
+ var text = texts[i];
+ if (text.selected && text.kind != TextType.POINTTEXT) {
+ var shape = text.textPath;
+ if (!hasSelectedAnchorPoints(shape)) continue;
+ items.push(shape);
+ }
+ }
+ return items;
+}
+
+
+function getValue(text) {
+ var twoByteChar = /[!-~]/g;
+ var value = text.replace(twoByteChar, function(str) {
+ return String.fromCharCode(str.charCodeAt(0) - 0xFEE0);
+ });
+ if (isNaN(value) || !value) return 0;
+ return Number(value);
+}
+
+
+function isValidVersion() {
+ var cs4 = 14;
+ var aiVersion = parseInt(app.version);
+ if (aiVersion < cs4) return false;
+ return true;
+}
+
+
function showDialog() {
$.localize = true;
var ui = localizeUI();
var dialog = new Window('dialog');
dialog.text = ui.title;
dialog.orientation = 'column';
- dialog.alignChildren = ['right', 'top'];
+ dialog.alignChildren = ['fill', 'top'];
dialog.spacing = 10;
dialog.margins = 16;
@@ -399,12 +402,12 @@ function showDialog() {
var edittext1 = group1.add('edittext', undefined, undefined, { name: 'edittext1' });
edittext1.text = '1';
- edittext1.preferredSize.width = 200;
+ edittext1.preferredSize.width = 180;
edittext1.active = true;
var group2 = dialog.add('group', undefined, { name: 'group2' });
group2.orientation = 'row';
- group2.alignChildren = ['left', 'center'];
+ group2.alignChildren = ['right', 'center'];
group2.spacing = 10;
group2.margins = 0;
@@ -416,6 +419,24 @@ function showDialog() {
button2.text = ui.ok;
button2.preferredSize.width = 90;
+ edittext1.addEventListener('keydown', function(event) {
+ var value = getValue(this.text);
+ var keyboard = ScriptUI.environment.keyboardState;
+ var step = keyboard.shiftKey ? 5 : 1;
+ var points;
+ if (event.keyName == 'Up') {
+ points = value + step;
+ this.text = points;
+ event.preventDefault();
+ }
+ if (event.keyName == 'Down') {
+ points = value - step;
+ if (points < 1) points = 1;
+ this.text = points;
+ event.preventDefault();
+ }
+ });
+
statictext1.addEventListener('click', function() {
edittext1.active = false;
edittext1.active = true;
diff --git a/scripts/alignInCenterOfSpace(Horizontal).js b/scripts/alignInCenterOfSpace(Horizontal).js
index 5fbb373..0fa5e2b 100755
--- a/scripts/alignInCenterOfSpace(Horizontal).js
+++ b/scripts/alignInCenterOfSpace(Horizontal).js
@@ -2,23 +2,23 @@
alignInCenterOfSpace(Horizontal)
Description
- This script aligns objects in the center of space.
+ This script aligns objects horizontally in the center of space.
Usage
- Select objects, run this script from File > Scripts > Other Script...
+ Select three or more objects, run this script from File > Scripts > Other Script...
The position of alignment depends on the reference point.
Notes
- The space excludes the stroke width.
+ Include or exclude the stroke width depends on the Align panel menu > Use Preview Bounds.
Select at least three objects.
- In rare cases, if you continue to use the script, it may not work.
- In that case, restart Illustrator and try again.
+ In rare cases, the script may not work if you continue to use it.
+ In this case, restart Illustrator and try again.
Requirements
Illustrator CS3 or higher
Version
- 1.0.0
+ 1.1.0
Homepage
github.com/sky-chaser-high/adobe-illustrator-scripts
@@ -29,64 +29,83 @@
=============================================================================================================================================== */
(function() {
- if (app.documents.length > 0 && app.activeDocument.selection.length > 2) main();
+ if (app.documents.length && isValidVersion()) main();
})();
function main() {
var items = app.activeDocument.selection;
- var baseItems = getBaseItems(items);
- var targetItems = getTargetItems(items, baseItems.left, baseItems.right);
+ if (items.length < 3) return;
- var space = getSpace(baseItems.left, baseItems.right);
- var center = baseItems.left.visibleBounds[2] + space / 2;
+ var baseItems = getBaseItems(items);
+ var targetItems = getTargetItems(items, baseItems);
- align(targetItems, center);
+ align(targetItems, baseItems);
}
-function align(items, center) {
- for (var i = 0; i < items.length; i++) {
- var distance = getMovingDistance(items[i], center);
- items[i].translate(distance);
+function align(targetItems, baseItems) {
+ var space = getSpace(baseItems);
+ var center = getCenter(baseItems.left, space);
+ for (var i = 0; i < targetItems.length; i++) {
+ var item = targetItems[i];
+ var distance = getDistance(item, center);
+ item.translate(distance);
}
}
-function getMovingDistance(item, center) {
- var referencePoint = getReferencePoint(item);
- var position = item.visibleBounds[0] + referencePoint;
+function getDistance(item, center) {
+ var width = getWidth(item);
+ var bounds = getBounds(item);
+ var position = bounds.left + width;
return center - position;
}
-function getReferencePoint(item) {
- var ref = app.preferences.getIntegerPreference("plugin/Transform/AnchorPoint");
- var width = item.visibleBounds[2] - item.visibleBounds[0];
- if (/[036]/.test(ref)) return 0;
- if (/[147]/.test(ref)) return width / 2;
- if (/[258]/.test(ref)) return width;
+function getWidth(item) {
+ var pref = app.preferences;
+ var point = pref.getIntegerPreference('plugin/Transform/AnchorPoint');
+ var bounds = getBounds(item);
+ var width = bounds.right - bounds.left;
+ if (/[036]/.test(point)) return 0;
+ if (/[147]/.test(point)) return width / 2;
+ if (/[258]/.test(point)) return width;
}
-function getSpace(leftItem, rightItem) {
- var left = leftItem.visibleBounds[2];
- var right = rightItem.visibleBounds[0];
+function getSpace(baseItems) {
+ var bounds = getBounds(baseItems.left);
+ var left = bounds.right;
+ bounds = getBounds(baseItems.right);
+ var right = bounds.left;
return Math.abs(right - left);
}
+function getCenter(item, space) {
+ var bounds = getBounds(item);
+ return bounds.right + space / 2;
+}
+
+
function getBaseItems(selection) {
var leftItem = selection[0];
var rightItem = selection[0];
for (var i = 1; i < selection.length; i++) {
- var left = leftItem.geometricBounds[0];
- var right = rightItem.geometricBounds[0];
- var target = selection[i].geometricBounds[0];
+ var item = selection[i];
+ var bounds = getBounds(item);
+ var target = bounds.left;
- if (target < left) leftItem = selection[i];
- if (target > right) rightItem = selection[i];
+ bounds = getBounds(leftItem);
+ var left = bounds.left;
+
+ bounds = getBounds(rightItem);
+ var right = bounds.left;
+
+ if (target < left) leftItem = item;
+ if (target > right) rightItem = item;
}
return {
@@ -96,13 +115,41 @@ function getBaseItems(selection) {
}
-function getTargetItems(selection, leftItem, rightItem) {
+function getTargetItems(selection, baseItem) {
var items = [];
for (var i = 0; i < selection.length; i++) {
- var left = leftItem.geometricBounds[0];
- var right = rightItem.geometricBounds[0];
- var target = selection[i].geometricBounds[0];
- if (left < target && target < right) items.push(selection[i]);
+ var item = selection[i];
+ var bounds = getBounds(item);
+ var target = bounds.left;
+
+ bounds = getBounds(baseItem.left);
+ var left = bounds.left;
+
+ bounds = getBounds(baseItem.right);
+ var right = bounds.left;
+
+ if (left < target && target < right) items.push(item);
}
return items;
}
+
+
+function getBounds(item) {
+ var pref = app.preferences;
+ var usePreviewBounds = pref.getBooleanPreference('includeStrokeInBounds');
+ var bounds = usePreviewBounds ? item.visibleBounds : item.geometricBounds;
+ return {
+ top: bounds[1],
+ left: bounds[0],
+ bottom: bounds[3],
+ right: bounds[2]
+ };
+}
+
+
+function isValidVersion() {
+ var cs3 = 13;
+ var aiVersion = parseInt(app.version);
+ if (aiVersion < cs3) return false;
+ return true;
+}
diff --git a/scripts/alignInCenterOfSpace(Vertical).js b/scripts/alignInCenterOfSpace(Vertical).js
index b1c894f..51eff6c 100755
--- a/scripts/alignInCenterOfSpace(Vertical).js
+++ b/scripts/alignInCenterOfSpace(Vertical).js
@@ -2,23 +2,23 @@
alignInCenterOfSpace(Vertical)
Description
- This script aligns objects in the center of space.
+ This script aligns objects vertically in the center of space.
Usage
- Select objects, run this script from File > Scripts > Other Script...
+ Select three or more objects, run this script from File > Scripts > Other Script...
The position of alignment depends on the reference point.
Notes
- The space excludes the stroke width.
+ Include or exclude the stroke width depends on the Align panel menu > Use Preview Bounds.
Select at least three objects.
- In rare cases, if you continue to use the script, it may not work.
- In that case, restart Illustrator and try again.
+ In rare cases, the script may not work if you continue to use it.
+ In this case, restart Illustrator and try again.
Requirements
Illustrator CS3 or higher
Version
- 1.0.0
+ 1.1.0
Homepage
github.com/sky-chaser-high/adobe-illustrator-scripts
@@ -29,64 +29,83 @@
=============================================================================================================================================== */
(function() {
- if (app.documents.length > 0 && app.activeDocument.selection.length > 2) main();
+ if (app.documents.length && isValidVersion()) main();
})();
function main() {
var items = app.activeDocument.selection;
- var baseItems = getBaseItems(items);
- var targetItems = getTargetItems(items, baseItems.top, baseItems.bottom);
+ if (items.length < 3) return;
- var space = getSpace(baseItems.top, baseItems.bottom);
- var center = baseItems.top.visibleBounds[3] - space / 2;
+ var baseItems = getBaseItems(items);
+ var targetItems = getTargetItems(items, baseItems);
- align(targetItems, center);
+ align(targetItems, baseItems);
}
-function align(items, center) {
- for (var i = 0; i < items.length; i++) {
- var distance = getMovingDistance(items[i], center);
- items[i].translate(0, distance);
+function align(targetItems, baseItems) {
+ var space = getSpace(baseItems);
+ var center = getCenter(baseItems.top, space);
+ for (var i = 0; i < targetItems.length; i++) {
+ var item = targetItems[i];
+ var distance = getDistance(item, center);
+ item.translate(0, distance);
}
}
-function getMovingDistance(item, center) {
- var referencePoint = getReferencePoint(item);
- var position = item.visibleBounds[1] - referencePoint;
+function getDistance(item, center) {
+ var height = getHeight(item);
+ var bounds = getBounds(item);
+ var position = bounds.top - height;
return center - position;
}
-function getReferencePoint(item) {
- var ref = app.preferences.getIntegerPreference("plugin/Transform/AnchorPoint");
- var height = item.visibleBounds[1] - item.visibleBounds[3];
- if (/[012]/.test(ref)) return 0;
- if (/[345]/.test(ref)) return height / 2;
- if (/[678]/.test(ref)) return height;
+function getHeight(item) {
+ var pref = app.preferences;
+ var point = pref.getIntegerPreference('plugin/Transform/AnchorPoint');
+ var bounds = getBounds(item);
+ var height = bounds.top - bounds.bottom;
+ if (/[012]/.test(point)) return 0;
+ if (/[345]/.test(point)) return height / 2;
+ if (/[678]/.test(point)) return height;
}
-function getSpace(topItem, bottomItem) {
- var top = topItem.visibleBounds[3];
- var bottom = bottomItem.visibleBounds[1];
+function getSpace(baseItems) {
+ var bounds = getBounds(baseItems.top);
+ var top = bounds.bottom;
+ bounds = getBounds(baseItems.bottom);
+ var bottom = bounds.top;
return Math.abs(top - bottom);
}
+function getCenter(item, space) {
+ var bounds = getBounds(item);
+ return bounds.bottom - space / 2;
+}
+
+
function getBaseItems(selection) {
var topItem = selection[0];
var bottomItem = selection[0];
for (var i = 1; i < selection.length; i++) {
- var top = topItem.geometricBounds[1];
- var bottom = bottomItem.geometricBounds[1];
- var target = selection[i].geometricBounds[1];
+ var item = selection[i];
+ var bounds = getBounds(item);
+ var target = bounds.top;
- if (target > top) topItem = selection[i];
- if (target < bottom) bottomItem = selection[i];
+ bounds = getBounds(topItem);
+ var top = bounds.top;
+
+ bounds = getBounds(bottomItem);
+ var bottom = bounds.top;
+
+ if (target > top) topItem = item;
+ if (target < bottom) bottomItem = item;
}
return {
@@ -96,13 +115,41 @@ function getBaseItems(selection) {
}
-function getTargetItems(selection, topItem, bottomItem) {
+function getTargetItems(selection, baseItem) {
var items = [];
for (var i = 0; i < selection.length; i++) {
- var top = topItem.geometricBounds[1];
- var bottom = bottomItem.geometricBounds[1];
- var target = selection[i].geometricBounds[1];
- if (top > target && target > bottom) items.push(selection[i]);
+ var item = selection[i];
+ var bounds = getBounds(item);
+ var target = bounds.top;
+
+ bounds = getBounds(baseItem.top);
+ var top = bounds.top;
+
+ bounds = getBounds(baseItem.bottom);
+ var bottom = bounds.top;
+
+ if (bottom < target && target < top) items.push(item);
}
return items;
}
+
+
+function getBounds(item) {
+ var pref = app.preferences;
+ var usePreviewBounds = pref.getBooleanPreference('includeStrokeInBounds');
+ var bounds = usePreviewBounds ? item.visibleBounds : item.geometricBounds;
+ return {
+ top: bounds[1],
+ left: bounds[0],
+ bottom: bounds[3],
+ right: bounds[2]
+ };
+}
+
+
+function isValidVersion() {
+ var cs3 = 13;
+ var aiVersion = parseInt(app.version);
+ if (aiVersion < cs3) return false;
+ return true;
+}
diff --git a/scripts/alignObjects.js b/scripts/alignObjects.js
index 8f8b9cb..0bf399e 100755
--- a/scripts/alignObjects.js
+++ b/scripts/alignObjects.js
@@ -14,8 +14,8 @@
Notes
The top row and the left-most column are the basis for alignment.
- The units of the Distribute Spacing and the Alignment Position Tolerance depend on the ruler units.
Compound paths, texts, linked files, and embedded link files are also supported.
+ The units of the Distribute Spacing and the Alignment Position Tolerance depend on the ruler units.
In rare cases, the script may not work if you continue to use it.
In this case, restart Illustrator and try again.
@@ -23,7 +23,7 @@
Illustrator 2021 or higher
Version
- 1.0.0
+ 1.1.0
Homepage
github.com/sky-chaser-high/adobe-illustrator-scripts
@@ -45,9 +45,7 @@ function main() {
var undoCount = 0;
- var ruler = app.activeDocument.rulerUnits;
- var units = getUnits(ruler);
- var dialog = showDialog(units);
+ var dialog = showDialog();
dialog.align.topLeft.addEventListener('click', function() {
var align = {
@@ -346,12 +344,6 @@ function getConfiguration(dialog, items) {
}
-function getValue(item) {
- if (isNaN(item)) return 0;
- return Number(item);
-}
-
-
function alignHorizontally(align, items, hasStroke) {
var columns = items.columns;
for (var i = 0; i < columns.length; i++) {
@@ -725,6 +717,16 @@ function getPageItems(items) {
}
+function getValue(text) {
+ var twoByteChar = /[!-~]/g;
+ var value = text.replace(twoByteChar, function(str) {
+ return String.fromCharCode(str.charCodeAt(0) - 0xFEE0);
+ });
+ if (isNaN(value) || !value) return 0;
+ return Number(value);
+}
+
+
function convertUnits(value, unit) {
try {
return Number(UnitValue(value).as(unit));
@@ -735,25 +737,81 @@ function convertUnits(value, unit) {
}
-function getUnits(unit) {
- switch (unit) {
- case RulerUnits.Millimeters: return 'mm';
- case RulerUnits.Centimeters: return 'cm';
- case RulerUnits.Inches: return 'inch';
- case RulerUnits.Points: return 'pt';
- case RulerUnits.Pixels: return 'px';
- default: return 'pt';
+function getRulerUnits() {
+ var unit = getUnitSymbol();
+ if (!app.documents.length) return unit.pt;
+
+ var document = app.activeDocument;
+ var src = document.fullName;
+ var ruler = document.rulerUnits;
+ try {
+ switch (ruler) {
+ case RulerUnits.Pixels: return unit.px;
+ case RulerUnits.Points: return unit.pt;
+ case RulerUnits.Picas: return unit.pc;
+ case RulerUnits.Inches: return unit.inch;
+ case RulerUnits.Millimeters: return unit.mm;
+ case RulerUnits.Centimeters: return unit.cm;
+
+ case RulerUnits.Feet: return unit.ft;
+ case RulerUnits.Yards: return unit.yd;
+ case RulerUnits.Meters: return unit.meter;
+ }
+ }
+ catch (err) {
+ switch (xmpRulerUnits(src)) {
+ case 'Feet': return unit.ft;
+ case 'Yards': return unit.yd;
+ case 'Meters': return unit.meter;
+ }
}
+ return unit.pt;
+}
+
+
+function xmpRulerUnits(src) {
+ if (!ExternalObject.AdobeXMPScript) {
+ ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
+ }
+ var xmpFile = new XMPFile(src.fsName, XMPConst.FILE_UNKNOWN, XMPConst.OPEN_FOR_READ);
+ var xmpPackets = xmpFile.getXMP();
+ var xmp = new XMPMeta(xmpPackets.serialize());
+
+ var namespace = 'http://ns.adobe.com/xap/1.0/t/pg/';
+ var prop = 'xmpTPg:MaxPageSize';
+ var unit = prop + '/stDim:unit';
+
+ var ruler = xmp.getProperty(namespace, unit).value;
+ return ruler;
+}
+
+
+function getUnitSymbol() {
+ return {
+ px: 'px',
+ pt: 'pt',
+ pc: 'pc',
+ inch: 'in',
+ ft: 'ft',
+ yd: 'yd',
+ mm: 'mm',
+ cm: 'cm',
+ meter: 'm'
+ };
}
function getTolerance(unit) {
switch (unit) {
+ case 'px': return 30;
+ case 'pt': return 30;
+ case 'pc': return 1;
+ case 'in': return 0.5;
+ case 'ft': return 0.03;
+ case 'yd': return 0.01;
case 'mm': return 10;
case 'cm': return 1;
- case 'inch': return 0.5;
- case 'pt': return 30;
- case 'px': return 30;
+ case 'm': return 0.01;
}
}
@@ -766,10 +824,12 @@ function isValidVersion() {
}
-function showDialog(units) {
+function showDialog() {
$.localize = true;
var ui = localizeUI();
var icon = getUIIcon();
+
+ var units = getRulerUnits();
var tolerance = getTolerance(units);
var dialog = new Window('dialog');
@@ -1207,43 +1267,8 @@ function showDialog(units) {
this.image = ScriptUI.newImage(File.decode(icon.normal.bottom));
});
- edittext1.addEventListener('keydown', function(event) {
- var value = Number(edittext1.text);
- if (isNaN(value)) value = 0;
- var keyboard = ScriptUI.environment.keyboardState;
- var step = keyboard.shiftKey ? 5 : 1;
- var margin;
- if (event.keyName == 'Up') {
- margin = value + step;
- edittext1.text = margin;
- event.preventDefault();
- }
- if (event.keyName == 'Down') {
- margin = value - step;
- if (margin < 0) margin = 0;
- edittext1.text = margin;
- event.preventDefault();
- }
- });
-
- edittext2.addEventListener('keydown', function(event) {
- var value = Number(edittext2.text);
- if (isNaN(value)) value = 0;
- var keyboard = ScriptUI.environment.keyboardState;
- var step = keyboard.shiftKey ? 5 : 1;
- var tolerance;
- if (event.keyName == 'Up') {
- tolerance = value + step;
- edittext2.text = tolerance;
- event.preventDefault();
- }
- if (event.keyName == 'Down') {
- tolerance = value - step;
- if (tolerance < 0) tolerance = 0;
- edittext2.text = tolerance;
- event.preventDefault();
- }
- });
+ edittext1.addEventListener('keydown', setIncreaseDecrease);
+ edittext2.addEventListener('keydown', setIncreaseDecrease);
statictext2.addEventListener('click', function() {
edittext2.active = false;
@@ -1301,6 +1326,24 @@ function showDialog(units) {
}
+function setIncreaseDecrease(event) {
+ var value = getValue(event.target.text);
+ var keyboard = ScriptUI.environment.keyboardState;
+ var step = keyboard.shiftKey ? 5 : 1;
+ if (event.keyName == 'Up') {
+ value += step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+ if (event.keyName == 'Down') {
+ value -= step;
+ if (value < 0) value = 0;
+ event.target.text = value;
+ event.preventDefault();
+ }
+}
+
+
function getUIIcon() {
var lightest = {
normal: {
diff --git a/scripts/convertAllAnchorPointsToCorner.js b/scripts/convertAllAnchorPointsToCorner.js
index b6c7b3a..8498457 100755
--- a/scripts/convertAllAnchorPointsToCorner.js
+++ b/scripts/convertAllAnchorPointsToCorner.js
@@ -1,4 +1,4 @@
-/* ===============================================================================================================================================
+/* ===============================================================================================================================================
convertAllAnchorPointsToCorner
Description
@@ -7,18 +7,20 @@
but this script selects the entire object.
Usage
- Select the entire path with selection tool, run this script from File > Scripts > Other Script...
+ Select the entire path with the Selection Tool, run this script from File > Scripts > Other Script...
+ If you select anchor points with the Direct Selection Tool,
+ a dialog will show to convert all or only selected anchor points to corner points.
Notes
- It is not necessary to select anchor points with direct selection tool.
- In rare cases, you may not be able to create it.
- In that case, restart Illustrator and run this script again.
+ Anchor points for type on a path and area type are also supported.
+ In rare cases, the script may not work if you continue to use it.
+ In this case, restart Illustrator and try again.
Requirements
- Illustrator CS or higher
+ Illustrator CS4 or higher
Version
- 1.0.0
+ 1.1.0
Homepage
github.com/sky-chaser-high/adobe-illustrator-scripts
@@ -29,43 +31,159 @@
=============================================================================================================================================== */
(function() {
- if (app.documents.length > 0 && app.activeDocument.selection.length > 0) main();
+ if (app.documents.length && isValidVersion()) main();
})();
function main() {
- var items = getPathItems(app.activeDocument.selection);
- for (var i = 0; i < items.length; i++) {
- convertToCorner(items[i]);
+ var items = app.activeDocument.selection;
+ var shapes = getPathItems(items);
+ var texts = getTextPathItems();
+ shapes = shapes.concat(texts);
+ var isAll = true;
+
+ if (hasAnchorPointNoSelected(shapes)) {
+ var dialog = showDialog();
+ dialog.selected.onClick = function() {
+ isAll = false;
+ dialog.close();
+ }
+ dialog.cancel.onClick = function() {
+ shapes = [];
+ dialog.close();
+ }
+ dialog.show();
+ }
+
+ for (var i = 0; i < shapes.length; i++) {
+ var shape = shapes[i];
+ convertToCorner(shape, isAll);
}
}
-function convertToCorner(item) {
+function convertToCorner(item, isAll) {
var points = item.pathPoints;
for (var i = 0; i < points.length; i++) {
- var anchor = points[i].anchor;
- points[i].leftDirection = anchor;
- points[i].rightDirection = anchor;
+ var point = points[i];
+ if (!isAll && point.selected != PathPointSelection.ANCHORPOINT) continue;
+ point.leftDirection = point.anchor;
+ point.rightDirection = point.anchor;
+ }
+}
+
+
+function hasAnchorPointNoSelected(items) {
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ var points = item.pathPoints;
+ for (var j = 0; j < points.length; j++) {
+ var point = points[j];
+ if (point.selected != PathPointSelection.ANCHORPOINT) return true;
+ }
+ }
+ return false;
+}
+
+
+function getPathItems(items) {
+ var shapes = [];
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ if (item.typename == 'PathItem') {
+ shapes.push(item);
+ }
+ if (item.typename == 'GroupItem') {
+ shapes = shapes.concat(getPathItems(item.pageItems));
+ }
+ if (item.typename == 'CompoundPathItem') {
+ shapes = shapes.concat(getPathItems(item.pathItems));
+ }
}
+ return shapes;
}
-function getPathItems(selection) {
+function getTextPathItems() {
var items = [];
- for (var i = 0; i < selection.length; i++) {
- var item = selection[i];
- switch (item.typename) {
- case 'PathItem':
- items.push(item);
- break;
- case 'CompoundPathItem':
- items = items.concat(getPathItems(item.pathItems));
- break;
- case 'GroupItem':
- items = items.concat(getPathItems(item.pageItems));
- break;
+ var texts = app.activeDocument.textFrames;
+ for (var i = 0; i < texts.length; i++) {
+ var text = texts[i];
+ if (text.selected && text.kind != TextType.POINTTEXT) {
+ items.push(text.textPath);
}
}
return items;
}
+
+
+function isValidVersion() {
+ var cs4 = 14;
+ var aiVersion = parseInt(app.version);
+ if (aiVersion < cs4) return false;
+ return true;
+}
+
+
+function showDialog() {
+ $.localize = true;
+ var ui = localizeUI();
+
+ var dialog = new Window('dialog');
+ dialog.text = ui.title;
+ dialog.preferredSize.width = 240;
+ dialog.orientation = 'column';
+ dialog.alignChildren = ['fill', 'top'];
+ dialog.spacing = 10;
+ dialog.margins = 16;
+
+ var group1 = dialog.add('group', undefined, { name: 'group1' });
+ group1.orientation = 'column';
+ group1.alignChildren = ['fill', 'center'];
+ group1.spacing = 16;
+ group1.margins = 0;
+
+ var button1 = group1.add('button', undefined, undefined, { name: 'button1' });
+ button1.text = ui.all;
+ button1.active = true;
+
+ var button2 = group1.add('button', undefined, undefined, { name: 'button2' });
+ button2.text = ui.selected;
+
+ var button3 = group1.add('button', undefined, undefined, { name: 'button3' });
+ button3.text = ui.cancel;
+
+ button1.onClick = function() {
+ dialog.close();
+ }
+
+ dialog.selected = button2;
+ dialog.cancel = button3;
+ return dialog;
+}
+
+
+function localizeUI() {
+ return {
+ title: {
+ en: 'Convert Anchor Points to Corner',
+ ja: 'コーナーポイントに切り替え'
+ },
+ all: {
+ en: 'All Anchor Points',
+ ja: 'すべてのアンカーポイント'
+ },
+ selected: {
+ en: 'Only Selected Anchor Points',
+ ja: '選択したアンカーポイントのみ'
+ },
+ cancel: {
+ en: 'Cancel',
+ ja: 'キャンセル'
+ },
+ ok: {
+ en: 'OK',
+ ja: 'OK'
+ }
+ };
+}
diff --git a/scripts/createTextParallelToPathSegment.js b/scripts/createTextParallelToPathSegment.js
index a8a5a43..9242426 100755
--- a/scripts/createTextParallelToPathSegment.js
+++ b/scripts/createTextParallelToPathSegment.js
@@ -12,12 +12,12 @@
Point Type: Select Left-align, Center-align, or Right-align.
Area Type: Enter area width and height values.
4. Check the Flip checkbox reverses the drawing position.
- 5. Check the Middle checkbox to draw in the middle of the line.
- 6. Enter a value of the margin will space them from the line.
+ 5. Check the Middle checkbox to draw in the middle of the path segment.
+ 6. Enter a value of the margin will space them from the path segment.
Notes
- Anchor points for type on a path and area type are supported.
Curves are not supported.
+ Anchor points for type on a path and area type are also supported.
The units of the Width, Height and Margin value depend on the ruler units.
In rare cases, the script may not work if you continue to use it.
In this case, restart Illustrator and try again.
@@ -26,7 +26,7 @@
Illustrator 2021 or higher
Version
- 1.0.0
+ 1.0.1
Homepage
github.com/sky-chaser-high/adobe-illustrator-scripts
@@ -45,7 +45,7 @@ function main() {
var items = app.activeDocument.selection;
var shapes = getPathItems(items);
var texts = getTextPathItems();
- var points = getAnchorPoints(shapes.concat(texts));
+ var points = getSelectedAnchorPoints(shapes.concat(texts));
if (points.length != 2) return;
var contents = setContents(points);
@@ -57,92 +57,6 @@ function main() {
app.redraw();
var dialog = showDialog(contents, points);
-
- dialog.contents.onChanging = function() {
- var config = getConfiguration(dialog);
- app.undo();
- addText(config, points);
- app.redraw();
- }
-
- dialog.kind.pointType.onClick = function() {
- dialog.kind.areaType.value = false;
- dialog.options.pointType.enabled = true;
- dialog.options.areaType.enabled = false;
- var config = getConfiguration(dialog);
- app.undo();
- addText(config, points);
- app.redraw();
- }
-
- dialog.kind.areaType.onClick = function() {
- dialog.kind.pointType.value = false;
- dialog.options.pointType.enabled = false;
- dialog.options.areaType.enabled = true;
- dialog.area.width.active = false;
- dialog.area.width.active = true;
- var config = getConfiguration(dialog);
- app.undo();
- addText(config, points);
- app.redraw();
- }
-
- dialog.align.left.onClick = function() {
- var config = getConfiguration(dialog);
- app.undo();
- addText(config, points);
- app.redraw();
- }
-
- dialog.align.center.onClick = function() {
- var config = getConfiguration(dialog);
- app.undo();
- addText(config, points);
- app.redraw();
- }
-
- dialog.align.right.onClick = function() {
- var config = getConfiguration(dialog);
- app.undo();
- addText(config, points);
- app.redraw();
- }
-
- dialog.area.width.onChanging = function() {
- var config = getConfiguration(dialog);
- app.undo();
- addText(config, points);
- app.redraw();
- }
-
- dialog.area.height.onChanging = function() {
- var config = getConfiguration(dialog);
- app.undo();
- addText(config, points);
- app.redraw();
- }
-
- dialog.flip.onClick = function() {
- var config = getConfiguration(dialog);
- app.undo();
- addText(config, points);
- app.redraw();
- }
-
- dialog.middle.onClick = function() {
- var config = getConfiguration(dialog);
- app.undo();
- addText(config, points);
- app.redraw();
- }
-
- dialog.margin.onChanging = function() {
- var config = getConfiguration(dialog);
- app.undo();
- addText(config, points);
- app.redraw();
- }
-
dialog.show();
}
@@ -157,8 +71,8 @@ function getConfiguration(dialog) {
if (dialog.align.right.value) align = Justification.RIGHT;
if (kind == TextType.AREATEXT) align = Justification.LEFT;
- var width = dialog.area.width.text;
- var height = dialog.area.height.text;
+ var width = getValue(dialog.area.width.text);
+ var height = getValue(dialog.area.height.text);
var flip = (dialog.flip.value) ? true : false;
var middle = (dialog.middle.value) ? true : false;
@@ -180,12 +94,23 @@ function getConfiguration(dialog) {
}
+function preview(dialog, points) {
+ reset(points);
+ var config = getConfiguration(dialog);
+ addText(config, points);
+ app.redraw();
+}
+
+
function setContents(points) {
+ var p1 = setPoint(points[0]);
+ var p2 = setPoint(points[1]);
+
var ruler = getRulerUnits();
- var length = getLength(points[0], points[1]);
+ var length = getLength(p1, p2);
length = convertUnits(length + 'pt', ruler);
- var rad = getAngle(points[0], points[1]);
+ var rad = getAngle(p1, p2);
var deg = rad * 180 / Math.PI;
var digits = 10000;
@@ -211,8 +136,8 @@ function addText(config, points) {
function createPointType(contents, points, align, margin, isFlip, isMiddle) {
- var p1 = isFlip ? points[1] : points[0];
- var p2 = isFlip ? points[0] : points[1];
+ var p1 = isFlip ? setPoint(points[1]) : setPoint(points[0]);
+ var p2 = isFlip ? setPoint(points[0]) : setPoint(points[1]);
var rad = getAngle(p1, p2);
var deg = rad * 180 / Math.PI;
@@ -246,8 +171,8 @@ function createPointType(contents, points, align, margin, isFlip, isMiddle) {
function createAreaType(contents, points, area, align, margin, isFlip, isMiddle) {
- var p1 = isFlip ? points[1] : points[0];
- var p2 = isFlip ? points[0] : points[1];
+ var p1 = isFlip ? setPoint(points[1]) : setPoint(points[0]);
+ var p2 = isFlip ? setPoint(points[0]) : setPoint(points[1]);
var rad = getAngle(p1, p2);
var deg = rad * 180 / Math.PI;
@@ -351,7 +276,15 @@ function getAngle(point1, point2) {
}
-function getAnchorPoints(shapes) {
+function setPoint(item) {
+ return {
+ x: item.anchor[0],
+ y: item.anchor[1]
+ };
+}
+
+
+function getSelectedAnchorPoints(shapes) {
var ANCHOR = PathPointSelection.ANCHORPOINT;
var anchors = [];
for (var i = 0; i < shapes.length; i++) {
@@ -359,7 +292,7 @@ function getAnchorPoints(shapes) {
for (var j = 0; j < points.length; j++) {
var point = points[j];
if (point.selected != ANCHOR) continue;
- anchors.push({ x: point.anchor[0], y: point.anchor[1] });
+ anchors.push(point);
}
}
return anchors;
@@ -382,13 +315,11 @@ function getPathItems(items) {
function getTextPathItems() {
- var AREA = TextType.AREATEXT;
- var PATH = TextType.PATHTEXT;
var items = [];
var texts = app.activeDocument.textFrames;
for (var i = 0; i < texts.length; i++) {
var text = texts[i];
- if (text.selected && (text.kind == AREA || text.kind == PATH)) {
+ if (text.selected && text.kind != TextType.POINTTEXT) {
items.push(text.textPath);
}
}
@@ -396,9 +327,27 @@ function getTextPathItems() {
}
+function reset(items) {
+ app.undo();
+ var ANCHOR = PathPointSelection.ANCHORPOINT;
+ var NOSELECTION = PathPointSelection.NOSELECTION;
+ for (var i = 0; i < items.length; i++) {
+ var points = items[i].parent.pathPoints;
+ for (var j = 0; j < points.length; j++) {
+ var point = points[j];
+ point.selected = NOSELECTION;
+ }
+ }
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ item.selected = ANCHOR;
+ }
+}
+
+
function getValue(text) {
var twoByteChar = /[!-~]/g;
- var value = text.replace(twoByteChar, function (str) {
+ var value = text.replace(twoByteChar, function(str) {
return String.fromCharCode(str.charCodeAt(0) - 0xFEE0);
});
if (isNaN(value) || !value) return 0;
@@ -498,7 +447,9 @@ function showDialog(contents, points) {
$.localize = true;
var ui = localizeUI();
var ruler = getRulerUnits();
- var length = getLength(points[0], points[1]);
+ var p1 = setPoint(points[0]);
+ var p2 = setPoint(points[1]);
+ var length = getLength(p1, p2);
length = convertUnits(length + 'pt', ruler);
var dialog = new Window('dialog');
@@ -523,7 +474,6 @@ function showDialog(contents, points) {
var edittext1 = group1.add('edittext', undefined, undefined, { name: 'edittext1', multiline: true });
edittext1.text = contents;
- // edittext1.text = ui.contents;
edittext1.preferredSize.height = 100;
edittext1.active = true;
@@ -685,6 +635,12 @@ function showDialog(contents, points) {
group15.spacing = 10;
group15.margins = 0;
+ // Work around the problem of not being able to undo with the esc key due to localization.
+ var button0 = group15.add('button', undefined, undefined, { name: 'button0' });
+ button0.text = 'Cancel';
+ button0.preferredSize.width = 20;
+ button0.hide();
+
var button1 = group15.add('button', undefined, undefined, { name: 'button1' });
button1.text = ui.cancel;
button1.preferredSize.width = 90;
@@ -693,6 +649,73 @@ function showDialog(contents, points) {
button2.text = ui.ok;
button2.preferredSize.width = 90;
+ edittext1.onChanging = function() {
+ preview(dialog, points);
+ }
+
+ radiobutton1.onClick = function() {
+ radiobutton5.value = false;
+ group4.enabled = true;
+ group9.enabled = false;
+ preview(dialog, points);
+ }
+
+ radiobutton5.onClick = function() {
+ radiobutton1.value = false;
+ group4.enabled = false;
+ group9.enabled = true;
+ edittext2.active = false;
+ edittext2.active = true;
+ preview(dialog, points);
+ }
+
+ radiobutton2.onClick = function() {
+ preview(dialog, points);
+ }
+
+ radiobutton3.onClick = function() {
+ preview(dialog, points);
+ }
+
+ radiobutton4.onClick = function() {
+ preview(dialog, points);
+ }
+
+ edittext2.onChanging = function() {
+ preview(dialog, points);
+ }
+
+ edittext3.onChanging = function() {
+ preview(dialog, points);
+ }
+
+ checkbox1.onClick = function() {
+ preview(dialog, points);
+ }
+
+ checkbox2.onClick = function() {
+ preview(dialog, points);
+ }
+
+ edittext4.onChanging = function() {
+ preview(dialog, points);
+ }
+
+ edittext2.addEventListener('keydown', function(event) {
+ setSizeValue(event);
+ preview(dialog, points);
+ });
+
+ edittext3.addEventListener('keydown', function(event) {
+ setSizeValue(event);
+ preview(dialog, points);
+ });
+
+ edittext4.addEventListener('keydown', function(event) {
+ setMarginValue(event);
+ preview(dialog, points);
+ });
+
statictext2.addEventListener('click', function() {
edittext2.active = false;
edittext2.active = true;
@@ -708,11 +731,15 @@ function showDialog(contents, points) {
edittext4.active = true;
});
- button1.onClick = function() {
- app.undo();
+ button0.onClick = function() {
+ reset(points);
dialog.close();
}
+ button1.onClick = function() {
+ button0.notify('onClick');
+ }
+
button2.onClick = function() {
dialog.close();
}
@@ -743,6 +770,41 @@ function showDialog(contents, points) {
}
+function setSizeValue(event) {
+ var value = getValue(event.target.text);
+ var keyboard = ScriptUI.environment.keyboardState;
+ var step = keyboard.shiftKey ? 5 : 1;
+ if (event.keyName == 'Up') {
+ value += step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+ if (event.keyName == 'Down') {
+ value -= step;
+ if (value < 1) value = 1;
+ event.target.text = value;
+ event.preventDefault();
+ }
+}
+
+
+function setMarginValue(event) {
+ var value = getValue(event.target.text);
+ var keyboard = ScriptUI.environment.keyboardState;
+ var step = keyboard.shiftKey ? 5 : 1;
+ if (event.keyName == 'Up') {
+ value += step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+ if (event.keyName == 'Down') {
+ value -= step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+}
+
+
function localizeUI() {
return {
title: {
diff --git a/scripts/distributeInSpace(Horizontal).js b/scripts/distributeInSpace(Horizontal).js
index 99d4b56..11c9d4b 100755
--- a/scripts/distributeInSpace(Horizontal).js
+++ b/scripts/distributeInSpace(Horizontal).js
@@ -2,23 +2,23 @@
distributeInSpace(Horizontal)
Description
- This script distributes objects evenly spaced in space.
+ This script distributes horizontally objects evenly spaced in space.
Usage
- Select objects, run this script from File > Scripts > Other Script...
+ Select three or more objects, run this script from File > Scripts > Other Script...
The position of alignment depends on the reference point.
Notes
- The space excludes the stroke width.
+ Include or exclude the stroke width depends on the Align panel menu > Use Preview Bounds.
Select at least three objects.
- In rare cases, if you continue to use the script, it may not work.
- In that case, restart Illustrator and try again.
+ In rare cases, the script may not work if you continue to use it.
+ In this case, restart Illustrator and try again.
Requirements
Illustrator CS3 or higher
Version
- 1.0.0
+ 1.1.0
Homepage
github.com/sky-chaser-high/adobe-illustrator-scripts
@@ -29,52 +29,59 @@
=============================================================================================================================================== */
(function() {
- if (app.documents.length > 0 && app.activeDocument.selection.length > 2) main();
+ if (app.documents.length && isValidVersion()) main();
})();
function main() {
var items = app.activeDocument.selection;
- var baseItems = getBaseItems(items);
- var targetItems = getTargetItems(items, baseItems.left, baseItems.right);
- targetItems.sort(leftToRight);
+ if (items.length < 3) return;
- var space = getSpace(baseItems.left, baseItems.right);
- var distribution = space / (targetItems.length + 1);
- var baseItem = baseItems.left.visibleBounds[2];
+ var baseItems = getBaseItems(items);
+ var targetItems = getTargetItems(items, baseItems);
- distribute(targetItems, baseItem, distribution);
+ distribute(targetItems, baseItems);
}
-function distribute(items, baseItem, distribution) {
- for (var i = 0; i < items.length; i++) {
- var target = baseItem + distribution * (i + 1);
- var distance = getMovingDistance(items[i], target);
- items[i].translate(distance);
+function distribute(targetItems, baseItems) {
+ var bounds = getBounds(baseItems.left);
+ var space = getSpace(baseItems);
+ var distribution = space / (targetItems.length + 1);
+
+ for (var i = 0; i < targetItems.length; i++) {
+ var item = targetItems[i];
+ var position = bounds.right + distribution * (i + 1);
+ var distance = getDistance(item, position);
+ item.translate(distance);
}
}
-function getMovingDistance(item, target) {
- var referencePoint = getReferencePoint(item);
- var position = item.visibleBounds[0] + referencePoint;
- return target - position;
+function getDistance(item, position) {
+ var width = getWidth(item);
+ var bounds = getBounds(item);
+ var distance = bounds.left + width;
+ return position - distance;
}
-function getReferencePoint(item) {
- var ref = app.preferences.getIntegerPreference("plugin/Transform/AnchorPoint");
- var width = item.visibleBounds[2] - item.visibleBounds[0];
- if (/[036]/.test(ref)) return 0;
- if (/[147]/.test(ref)) return width / 2;
- if (/[258]/.test(ref)) return width;
+function getWidth(item) {
+ var pref = app.preferences;
+ var point = pref.getIntegerPreference('plugin/Transform/AnchorPoint');
+ var bounds = getBounds(item);
+ var width = bounds.right - bounds.left;
+ if (/[036]/.test(point)) return 0;
+ if (/[147]/.test(point)) return width / 2;
+ if (/[258]/.test(point)) return width;
}
-function getSpace(leftItem, rightItem) {
- var left = leftItem.visibleBounds[2];
- var right = rightItem.visibleBounds[0];
+function getSpace(baseItems) {
+ var bounds = getBounds(baseItems.left);
+ var left = bounds.right;
+ bounds = getBounds(baseItems.right);
+ var right = bounds.left;
return Math.abs(right - left);
}
@@ -84,12 +91,18 @@ function getBaseItems(selection) {
var rightItem = selection[0];
for (var i = 1; i < selection.length; i++) {
- var left = leftItem.geometricBounds[0];
- var right = rightItem.geometricBounds[0];
- var target = selection[i].geometricBounds[0];
+ var item = selection[i];
+ var bounds = getBounds(item);
+ var target = bounds.left;
+
+ bounds = getBounds(leftItem);
+ var left = bounds.left;
- if (target < left) leftItem = selection[i];
- if (target > right) rightItem = selection[i];
+ bounds = getBounds(rightItem);
+ var right = bounds.left;
+
+ if (target < left) leftItem = item;
+ if (target > right) rightItem = item;
}
return {
@@ -99,20 +112,47 @@ function getBaseItems(selection) {
}
-function getTargetItems(selection, leftItem, rightItem) {
+function getTargetItems(selection, baseItem) {
var items = [];
for (var i = 0; i < selection.length; i++) {
- var left = leftItem.geometricBounds[0];
- var right = rightItem.geometricBounds[0];
- var target = selection[i].geometricBounds[0];
- if (left < target && target < right) items.push(selection[i]);
+ var item = selection[i];
+ var bounds = getBounds(item);
+ var target = bounds.left;
+
+ bounds = getBounds(baseItem.left);
+ var left = bounds.left;
+
+ bounds = getBounds(baseItem.right);
+ var right = bounds.left;
+
+ if (left < target && target < right) items.push(item);
}
+
+ items.sort(function(a, b) {
+ var boundsA = getBounds(a);
+ var boundsB = getBounds(b);
+ return boundsA.left - boundsB.left;
+ });
return items;
}
-function leftToRight(a, b) {
- var item1 = a.geometricBounds[0];
- var item2 = b.geometricBounds[0];
- return item1 - item2;
+function getBounds(item) {
+ var pref = app.preferences;
+ var usePreviewBounds = pref.getBooleanPreference('includeStrokeInBounds');
+ var bounds = usePreviewBounds ? item.visibleBounds : item.geometricBounds;
+ return {
+ top: bounds[1],
+ left: bounds[0],
+ bottom: bounds[3],
+ right: bounds[2]
+ };
+}
+
+
+function isValidVersion() {
+ var cs3 = 13;
+ var aiVersion = parseInt(app.version);
+ if (aiVersion < cs3) return false;
+ return true;
}
diff --git a/scripts/distributeInSpace(Vertical).js b/scripts/distributeInSpace(Vertical).js
index f2cc6c5..2c62e12 100755
--- a/scripts/distributeInSpace(Vertical).js
+++ b/scripts/distributeInSpace(Vertical).js
@@ -2,23 +2,23 @@
distributeInSpace(Vertical)
Description
- This script distributes objects evenly spaced in space.
+ This script distributes vertically objects evenly spaced in space.
Usage
- Select objects, run this script from File > Scripts > Other Script...
+ Select three or more objects, run this script from File > Scripts > Other Script...
The position of alignment depends on the reference point.
Notes
- The space excludes the stroke width.
+ Include or exclude the stroke width depends on the Align panel menu > Use Preview Bounds.
Select at least three objects.
- In rare cases, if you continue to use the script, it may not work.
- In that case, restart Illustrator and try again.
+ In rare cases, the script may not work if you continue to use it.
+ In this case, restart Illustrator and try again.
Requirements
Illustrator CS3 or higher
Version
- 1.0.0
+ 1.1.0
Homepage
github.com/sky-chaser-high/adobe-illustrator-scripts
@@ -29,52 +29,59 @@
=============================================================================================================================================== */
(function() {
- if (app.documents.length > 0 && app.activeDocument.selection.length > 2) main();
+ if (app.documents.length && isValidVersion()) main();
})();
function main() {
var items = app.activeDocument.selection;
- var baseItems = getBaseItems(items);
- var targetItems = getTargetItems(items, baseItems.top, baseItems.bottom);
- targetItems.sort(topToBottom);
+ if (items.length < 3) return;
- var space = getSpace(baseItems.top, baseItems.bottom);
- var distribution = space / (targetItems.length + 1);
- var baseItem = baseItems.top.visibleBounds[3];
+ var baseItems = getBaseItems(items);
+ var targetItems = getTargetItems(items, baseItems);
- distribute(targetItems, baseItem, distribution);
+ distribute(targetItems, baseItems);
}
-function distribute(items, baseItem, distribution) {
- for (var i = 0; i < items.length; i++) {
- var target = baseItem - distribution * (i + 1);
- var distance = getMovingDistance(items[i], target);
- items[i].translate(0, distance);
+function distribute(targetItems, baseItems) {
+ var bounds = getBounds(baseItems.top);
+ var space = getSpace(baseItems);
+ var distribution = space / (targetItems.length + 1);
+
+ for (var i = 0; i < targetItems.length; i++) {
+ var item = targetItems[i];
+ var position = bounds.bottom - distribution * (i + 1);
+ var distance = getDistance(item, position);
+ item.translate(0, distance);
}
}
-function getMovingDistance(item, target) {
- var referencePoint = getReferencePoint(item);
- var position = item.visibleBounds[1] - referencePoint;
- return target - position;
+function getDistance(item, position) {
+ var height = getHeight(item);
+ var bounds = getBounds(item);
+ var distance = bounds.top - height;
+ return position - distance;
}
-function getReferencePoint(item) {
- var ref = app.preferences.getIntegerPreference("plugin/Transform/AnchorPoint");
- var height = item.visibleBounds[1] - item.visibleBounds[3];
- if (/[012]/.test(ref)) return 0;
- if (/[345]/.test(ref)) return height / 2;
- if (/[678]/.test(ref)) return height;
+function getHeight(item) {
+ var pref = app.preferences;
+ var point = pref.getIntegerPreference('plugin/Transform/AnchorPoint');
+ var bounds = getBounds(item);
+ var height = bounds.top - bounds.bottom;
+ if (/[012]/.test(point)) return 0;
+ if (/[345]/.test(point)) return height / 2;
+ if (/[678]/.test(point)) return height;
}
-function getSpace(topItem, bottomItem) {
- var top = topItem.visibleBounds[3];
- var bottom = bottomItem.visibleBounds[1];
+function getSpace(baseItems) {
+ var bounds = getBounds(baseItems.top);
+ var top = bounds.bottom;
+ bounds = getBounds(baseItems.bottom);
+ var bottom = bounds.top;
return Math.abs(top - bottom);
}
@@ -84,12 +91,18 @@ function getBaseItems(selection) {
var bottomItem = selection[0];
for (var i = 1; i < selection.length; i++) {
- var top = topItem.geometricBounds[1];
- var bottom = bottomItem.geometricBounds[1];
- var target = selection[i].geometricBounds[1];
+ var item = selection[i];
+ var bounds = getBounds(item);
+ var target = bounds.top;
+
+ bounds = getBounds(topItem);
+ var top = bounds.top;
- if (target > top) topItem = selection[i];
- if (target < bottom) bottomItem = selection[i];
+ bounds = getBounds(bottomItem);
+ var bottom = bounds.top;
+
+ if (target > top) topItem = item;
+ if (target < bottom) bottomItem = item;
}
return {
@@ -99,20 +112,47 @@ function getBaseItems(selection) {
}
-function getTargetItems(selection, topItem, bottomItem) {
+function getTargetItems(selection, baseItem) {
var items = [];
for (var i = 0; i < selection.length; i++) {
- var top = topItem.geometricBounds[1];
- var bottom = bottomItem.geometricBounds[1];
- var target = selection[i].geometricBounds[1];
- if (top > target && target > bottom) items.push(selection[i]);
+ var item = selection[i];
+ var bounds = getBounds(item);
+ var target = bounds.top;
+
+ bounds = getBounds(baseItem.top);
+ var top = bounds.top;
+
+ bounds = getBounds(baseItem.bottom);
+ var bottom = bounds.top;
+
+ if (bottom < target && target < top) items.push(item);
}
+
+ items.sort(function(a, b) {
+ var boundsA = getBounds(a);
+ var boundsB = getBounds(b);
+ return boundsB.top - boundsA.top;
+ });
return items;
}
-function topToBottom(a, b) {
- var item1 = a.geometricBounds[1];
- var item2 = b.geometricBounds[1];
- return item2 - item1;
+function getBounds(item) {
+ var pref = app.preferences;
+ var usePreviewBounds = pref.getBooleanPreference('includeStrokeInBounds');
+ var bounds = usePreviewBounds ? item.visibleBounds : item.geometricBounds;
+ return {
+ top: bounds[1],
+ left: bounds[0],
+ bottom: bounds[3],
+ right: bounds[2]
+ };
+}
+
+
+function isValidVersion() {
+ var cs3 = 13;
+ var aiVersion = parseInt(app.version);
+ if (aiVersion < cs3) return false;
+ return true;
}
diff --git a/scripts/drawNormalLine.js b/scripts/drawNormalLine.js
new file mode 100755
index 0000000..9cc66dc
--- /dev/null
+++ b/scripts/drawNormalLine.js
@@ -0,0 +1,912 @@
+/* ===============================================================================================================================================
+ drawNormalLine
+
+ Description
+ This script draws normal lines (line perpendicular to a tangent) to a curve or line between two anchor points.
+
+ Usage
+ 1. Select two or more anchor points with the Direct Selection Tool, run this script from File > Scripts > Other Script...
+ 2. Enter the number of normal lines to draw.
+ 3. Enter the length of normal line to draw.
+ 4. Check the Draw on Selected Anchor Points checkbox if you want to draw on the selected anchor points.
+ 5. Check the Flip checkbox reverses the drawing position.
+ 6. Check the Middle checkbox to draw in the middle of the path segment.
+ 7. Enter a value of the margin will space them from the path segment.
+
+ Notes
+ Anchor points for type on a path and area type are not supported.
+ The units of the Length and Margin value depend on the ruler units.
+ In rare cases, the script may not work if you continue to use it.
+ In this case, restart Illustrator and try again.
+
+ Requirements
+ Illustrator CS4 or higher
+
+ Version
+ 1.0.0
+
+ Homepage
+ github.com/sky-chaser-high/adobe-illustrator-scripts
+
+ License
+ Released under the MIT license.
+ https://opensource.org/licenses/mit-license.php
+ =============================================================================================================================================== */
+
+(function() {
+ if (app.documents.length && isValidVersion()) main();
+})();
+
+
+function main() {
+ var items = app.activeDocument.selection;
+ var shapes = getPathItems(items);
+ var points = getSelectedAnchorPoints(shapes);
+ if (!shapes.length || !points.length) return;
+
+ var ruler = getRulerUnits();
+ var length = convertUnits('10' + ruler, 'pt');
+ showNormalLines(points, {
+ count: 1, length: length, include: false, margin: 0, flip: false, middle: false
+ });
+ app.redraw();
+
+ var dialog = showDialog(points);
+ dialog.show();
+}
+
+
+function getConfiguration(dialog) {
+ var count = getValue(dialog.lines.text);
+ if (count < 1) count = 1;
+ var length = getValue(dialog.length.text);
+ var include = dialog.include.value;
+ var flip = dialog.flip.value;
+ var middle = dialog.middle.value;
+ var margin = getValue(dialog.margin.text);
+ var units = dialog.units;
+ return {
+ count: parseInt(count),
+ length: convertUnits(length + units, 'pt'),
+ include: include,
+ flip: flip,
+ middle: middle,
+ margin: convertUnits(margin + units, 'pt')
+ };
+}
+
+
+function preview(dialog, points) {
+ reset(points);
+ var config = getConfiguration(dialog);
+ showNormalLines(points, config);
+ app.redraw();
+}
+
+
+function showNormalLines(points, config) {
+ for (var i = 0; i < points.length; i++) {
+ var positions = points[i];
+ if (!positions.length) continue;
+ drawNormalLines(
+ positions,
+ config.count,
+ config.length,
+ config.include,
+ config.margin,
+ config.flip,
+ config.middle
+ );
+ }
+}
+
+
+function drawNormalLines(positions, count, length, isInclude, margin, isFlip, isMiddle) {
+ var points = getNormalLinePositions(positions, count, length, isInclude);
+ for (var i = 0; i < points.anchor.length; i++) {
+ var anchor = points.anchor[i];
+ var handle = {
+ left: points.left[i],
+ right: points.right[i]
+ };
+ createLine(anchor, handle, length, margin, isFlip, isMiddle);
+ }
+}
+
+
+function createLine(anchor, handle, length, margin, isFlip, isMiddle) {
+ var point = (handle.left[0]) ? handle.left : handle.right;
+ var sign = (handle.left[0]) ? 1 : -1;
+ if (isFlip) sign *= -1;
+
+ var angle = getAngle(anchor, point);
+ var rad = angle - (Math.PI / 2) * sign;
+ var width = length * Math.cos(rad);
+ var height = length * Math.sin(rad);
+ var x1 = anchor[0];
+ var y1 = anchor[1];
+ var x2 = x1 + width;
+ var y2 = y1 + height;
+
+ var line = app.activeDocument.activeLayer.pathItems.add();
+ line.filled = false;
+ line.stroked = true;
+ line.strokeWidth = 1;
+ line.setEntirePath([[x1, y1], [x2, y2]]);
+
+ if (isMiddle) {
+ var center = getCenter([x1, y1], [x2, y2]);
+ line.translate(center.x, center.y);
+ }
+
+ if (margin) {
+ var distance = getDistance(margin, rad);
+ line.translate(distance.x, distance.y);
+ }
+}
+
+
+function getDistance(value, angle) {
+ var x = value * Math.cos(angle);
+ var y = value * Math.sin(angle);
+ return {
+ x: x,
+ y: y
+ };
+}
+
+
+function getAngle(point1, point2) {
+ var x = 0;
+ var y = 1;
+ var width = point2[x] - point1[x];
+ var height = point2[y] - point1[y];
+ return Math.atan2(height, width);
+}
+
+
+function getCenter(point1, point2) {
+ var x = 0;
+ var y = 1;
+ return {
+ x: (point1[x] - point2[x]) / 2,
+ y: (point1[y] - point2[y]) / 2
+ };
+}
+
+
+function getNormalLinePositions(positions, count, length, isInclude) {
+ var lines = {
+ anchor: [], left: [], right: []
+ };
+ var points;
+ for (var i = 0; i < positions.length; i++) {
+ var pos = positions[i];
+
+ if (isCurve(pos.point1, pos.point2)) {
+ points = getCurvedPoints(pos.point1, pos.point2, count);
+ }
+ else {
+ points = getLinearPoints(pos.point1, pos.point2, count, length);
+ }
+ if (!isInclude) removeSelectedAnchorPositions(points);
+ removeDupe(points, lines);
+
+ var insertPoint = [lines.anchor.length, 0];
+
+ lines.anchor = concatenate(lines.anchor, points.anchor, insertPoint);
+ lines.left = concatenate(lines.left, points.left, insertPoint);
+ lines.right = concatenate(lines.right, points.right, insertPoint);
+ }
+ return lines;
+}
+
+
+// Insert an array into an array to make a single array.
+// https://stackoverflow.com/questions/1348178/a-better-way-to-splice-an-array-into-an-array-in-javascript
+// Array.prototype.splice.apply(array1, [start, deleteCount].concat(array2));
+function concatenate(array1, array2, insertPoint) {
+ Array.prototype.splice.apply(array1, insertPoint.concat(array2));
+ return array1;
+}
+
+
+function removeSelectedAnchorPositions(points) {
+ points.anchor.pop();
+ points.left.pop();
+ points.right.pop();
+ points.anchor.shift();
+ points.left.shift();
+ points.right.shift();
+}
+
+
+function removeDupe(p1, p2) {
+ if (!p2.anchor.length) return;
+ var start = 0;
+ var end = p2.anchor.length - 1;
+ if (isSameCoordinates(p1.anchor[start], p2.anchor[end]) &&
+ isFlat(p1.anchor[start], p1.right[start], p2.anchor[end], p2.left[end])) {
+ p1.anchor.shift();
+ p1.left.shift();
+ p1.right.shift();
+ }
+ end = p1.anchor.length - 1;
+ if (isSameCoordinates(p1.anchor[end], p2.anchor[start]) &&
+ isFlat(p1.anchor[end], p1.left[end], p2.anchor[start], p2.right[start])) {
+ p1.anchor.pop();
+ p1.left.pop();
+ p1.right.pop();
+ }
+}
+
+
+function isFlat(anchor1, handle1, anchor2, handle2) {
+ var x = 0;
+ var y = 1;
+ var sq = 2;
+ var x1 = anchor1[x] - handle1[x];
+ var y1 = anchor1[y] - handle1[y];
+ var x2 = anchor2[x] - handle2[x];
+ var y2 = anchor2[y] - handle2[y];
+ var l1 = Math.sqrt(Math.pow(x1, sq) + Math.pow(y1, sq));
+ var l2 = Math.sqrt(Math.pow(x2, sq) + Math.pow(y2, sq));
+ // dot product
+ var cos = ((x1 * x2) + (y1 * y2)) / (l1 * l2);
+ return cos == 1 | cos == -1;
+}
+
+
+function isSameCoordinates(point1, point2) {
+ var x = 0;
+ var y = 1;
+ return point1[x] == point2[x] && point1[y] == point2[y];
+}
+
+
+function getLinearPoints(p1, p2, count, length) {
+ var points = count + 1;
+ var x1 = p1.anchor[0];
+ var y1 = p1.anchor[1];
+ var x2 = p2.anchor[0];
+ var y2 = p2.anchor[1];
+ var dx = (x2 - x1) / points;
+ var dy = (y2 - y1) / points;
+ var rad = getAngle(p1.anchor, p2.anchor);
+ var w = length * Math.cos(rad);
+ var h = length * Math.sin(rad);
+
+ var position = {
+ anchor: [[x1, y1]],
+ left: [[x1 - w, y1 - h]],
+ right: [[x1 - w, y1 - h]]
+ };
+
+ for (var i = 1; i < points; i++) {
+ var px = x1 + (dx * i);
+ var py = y1 + (dy * i);
+ position.anchor.push([px, py]);
+ position.left.push([px - w, py - h]);
+ position.right.push([px - w, py - h]);
+ }
+
+ position.anchor.push([x2, y2]);
+ position.left.push([x2 - w, y2 - h]);
+ position.right.push([x2 - w, y2 - h]);
+ return position;
+}
+
+
+function getCurvedPoints(p1, p2, count) {
+ var positions = [];
+ var points = count + 1;
+ var bezier = setBezier(p1, p2);
+ for (var i = 0; i < points; i++) {
+ var t1 = i / points;
+ var t2 = (i + 1) / points;
+ var curves = splitCurve(t1, t2, bezier);
+ positions.push(curves);
+ }
+ return formatPosition(positions);
+}
+
+
+function formatPosition(bezier) {
+ var start = 0;
+ var end = bezier.length - 1;
+
+ var position = {
+ anchor: [[bezier[start][0].x, bezier[start][0].y]],
+ left: [[undefined, undefined]],
+ right: [[bezier[start][1].x, bezier[start][1].y]]
+ };
+
+ for (var i = 0; i < end; i++) {
+ position.anchor.push([bezier[i][3].x, bezier[i][3].y]);
+ position.left.push([bezier[i][2].x, bezier[i][2].y]);
+ position.right.push([bezier[i + 1][1].x, bezier[i + 1][1].y]);
+ }
+
+ position.anchor.push([bezier[end][3].x, bezier[end][3].y]);
+ position.left.push([bezier[end][2].x, bezier[end][2].y]);
+ position.right.push([undefined, undefined]);
+ return position;
+}
+
+
+function setBezier(p1, p2) {
+ var anchor1 = {
+ x: p1.anchor[0],
+ y: p1.anchor[1]
+ };
+ var anchor2 = {
+ x: p2.anchor[0],
+ y: p2.anchor[1]
+ };
+ var handle1 = {
+ x: p1.rightDirection[0],
+ y: p1.rightDirection[1]
+ };
+ var handle2 = {
+ x: p2.leftDirection[0],
+ y: p2.leftDirection[1]
+ };
+ return [anchor1, handle1, handle2, anchor2];
+}
+
+
+function splitCurve(t1, t2, bezier) {
+ var anchor1 = getEndPoint(t1, bezier);
+ var handle1 = getControlPoint(t1, t2, bezier);
+ var handle2 = getControlPoint(t2, t1, bezier);
+ var anchor2 = getEndPoint(t2, bezier);
+ return [
+ { x: anchor1.x, y: anchor1.y },
+ { x: handle1.x, y: handle1.y },
+ { x: handle2.x, y: handle2.y },
+ { x: anchor2.x, y: anchor2.y }
+ ];
+}
+
+
+// B(t) = (1−t)^3 * P0 + 3 * (1−t)^2 * t * P1 + 3 * (1−t) * t^2 * P2 + t^3 * P3
+function getEndPoint(t, bezier) {
+ var _t = 1 - t;
+ return add(
+ add(
+ add(
+ mult(bezier[0], _t * _t * _t),
+ mult(bezier[1], 3 * _t * _t * t)
+ ),
+ mult(bezier[2], 3 * _t * t * t)
+ ),
+ mult(bezier[3], t * t * t)
+ );
+}
+
+
+// B(t1, t2) = (1−t1)^2 * ((1−t2) * P0 + t2 * P1) + 2 * (1−t1) * t1 * ((1−t2) * P1 + t2 * P2) + t1^2 * ((1−t2) * P2 + t2 * P3)
+function getControlPoint(t1, t2, bezier) {
+ var _t1 = 1 - t1;
+ var _t2 = 1 - t2;
+ return add(
+ add(
+ mult(
+ add(mult(bezier[0], _t2), mult(bezier[1], t2)),
+ _t1 * _t1
+ ),
+ mult(
+ add(mult(bezier[1], _t2), mult(bezier[2], t2)),
+ 2 * _t1 * t1
+ )
+ ),
+ mult(
+ add(mult(bezier[2], _t2), mult(bezier[3], t2)),
+ t1 * t1
+ )
+ );
+}
+
+
+function vector(v) {
+ return {
+ x: v.x,
+ y: v.y
+ };
+}
+
+
+function add(a, b) {
+ var v = vector(a);
+ v.x += b.x;
+ v.y += b.y;
+ return v;
+}
+
+
+function mult(a, t) {
+ var v = vector(a);
+ v.x *= t;
+ v.y *= t;
+ return v;
+}
+
+
+function hasHandle(anchor, handle) {
+ var x = 0;
+ var y = 1;
+ return anchor[x] != handle[x] || anchor[y] != handle[y];
+}
+
+
+function isCurve(p1, p2) {
+ var right = hasHandle(p1.anchor, p1.rightDirection);
+ var left = hasHandle(p2.anchor, p2.leftDirection);
+ return left || right;
+}
+
+
+function isSelected(shape, index) {
+ var ANCHOR = PathPointSelection.ANCHORPOINT;
+ var points = shape.pathPoints;
+
+ var p1 = points[index];
+ if (p1.selected != ANCHOR) return false;
+
+ var last = points.length - 1;
+ if (index == last && !shape.closed) return false;
+
+ var next = (index < last) ? index + 1 : 0;
+ var p2 = points[next];
+ if (p2.selected != ANCHOR) return false;
+ return true;
+}
+
+
+function getSelectedAnchorPoints(shapes) {
+ var anchors = [];
+ for (var i = 0, count = 0; i < shapes.length; i++) {
+ anchors.push([]);
+ var shape = shapes[i];
+ var points = shape.pathPoints;
+ for (var j = 0; j < points.length; j++) {
+ if (!isSelected(shape, j)) continue;
+ var p1 = points[j];
+ var last = points.length - 1;
+ var next = (j < last) ? j + 1 : 0;
+ var p2 = points[next];
+ anchors[count].push({
+ point1: p1,
+ point2: p2
+ });
+ }
+ if (!anchors[count].length) anchors.pop();
+ else count++;
+ }
+ return anchors;
+}
+
+
+function getPathItems(items) {
+ var shapes = [];
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ if (item.typename == 'PathItem') {
+ shapes.push(item);
+ }
+ if (item.typename == 'GroupItem') {
+ shapes = shapes.concat(getPathItems(item.pageItems));
+ }
+ if (item.typename == 'CompoundPathItem') {
+ shapes = shapes.concat(getPathItems(item.pathItems));
+ }
+ }
+ return shapes;
+}
+
+
+function reset(items) {
+ app.undo();
+ var ANCHOR = PathPointSelection.ANCHORPOINT;
+ var NOSELECTION = PathPointSelection.NOSELECTION;
+ var item, point, points;
+ for (var i = 0; i < items.length; i++) {
+ item = items[i][0].point1;
+ points = item.parent.pathPoints;
+ for (var j = 0; j < points.length; j++) {
+ point = points[j];
+ point.selected = NOSELECTION;
+ }
+ }
+ for (var i = 0; i < items.length; i++) {
+ points = items[i];
+ for (var j = 0; j < points.length; j++) {
+ point = points[j];
+ var point1 = point.point1;
+ point1.selected = ANCHOR;
+ var point2 = point.point2;
+ point2.selected = ANCHOR;
+ }
+ }
+}
+
+
+function getValue(text) {
+ var twoByteChar = /[!-~]/g;
+ var value = text.replace(twoByteChar, function(str) {
+ return String.fromCharCode(str.charCodeAt(0) - 0xFEE0);
+ });
+ if (isNaN(value) || !value) return 0;
+ return Number(value);
+}
+
+
+function convertUnits(value, unit) {
+ try {
+ return Number(UnitValue(value).as(unit));
+ }
+ catch (err) {
+ return Number(UnitValue('1pt').as('pt'));
+ }
+}
+
+
+function getRulerUnits() {
+ var unit = getUnitSymbol();
+ if (!app.documents.length) return unit.pt;
+
+ var document = app.activeDocument;
+ var src = document.fullName;
+ var ruler = document.rulerUnits;
+ try {
+ switch (ruler) {
+ case RulerUnits.Pixels: return unit.px;
+ case RulerUnits.Points: return unit.pt;
+ case RulerUnits.Picas: return unit.pc;
+ case RulerUnits.Inches: return unit.inch;
+ case RulerUnits.Millimeters: return unit.mm;
+ case RulerUnits.Centimeters: return unit.cm;
+
+ case RulerUnits.Feet: return unit.ft;
+ case RulerUnits.Yards: return unit.yd;
+ case RulerUnits.Meters: return unit.meter;
+ }
+ }
+ catch (err) {
+ switch (xmpRulerUnits(src)) {
+ case 'Feet': return unit.ft;
+ case 'Yards': return unit.yd;
+ case 'Meters': return unit.meter;
+ }
+ }
+ return unit.pt;
+}
+
+
+function xmpRulerUnits(src) {
+ if (!ExternalObject.AdobeXMPScript) {
+ ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
+ }
+ var xmpFile = new XMPFile(src.fsName, XMPConst.FILE_UNKNOWN, XMPConst.OPEN_FOR_READ);
+ var xmpPackets = xmpFile.getXMP();
+ var xmp = new XMPMeta(xmpPackets.serialize());
+
+ var namespace = 'http://ns.adobe.com/xap/1.0/t/pg/';
+ var prop = 'xmpTPg:MaxPageSize';
+ var unit = prop + '/stDim:unit';
+
+ var ruler = xmp.getProperty(namespace, unit).value;
+ return ruler;
+}
+
+
+function getUnitSymbol() {
+ return {
+ px: 'px',
+ pt: 'pt',
+ pc: 'pc',
+ inch: 'in',
+ ft: 'ft',
+ yd: 'yd',
+ mm: 'mm',
+ cm: 'cm',
+ meter: 'm'
+ };
+}
+
+
+function isValidVersion() {
+ var cs4 = 14;
+ var aiVersion = parseInt(app.version);
+ if (aiVersion < cs4) return false;
+ return true;
+}
+
+
+function showDialog(points) {
+ $.localize = true;
+ var ui = localizeUI();
+ var ruler = getRulerUnits();
+
+ var dialog = new Window('dialog');
+ dialog.text = ui.title;
+ dialog.orientation = 'column';
+ dialog.alignChildren = ['fill', 'top'];
+ dialog.spacing = 10;
+ dialog.margins = 16;
+
+ var panel1 = dialog.add('panel', undefined, undefined, { name: 'panel1' });
+ panel1.text = ui.normal;
+ panel1.orientation = 'column';
+ panel1.alignChildren = ['left', 'top'];
+ panel1.spacing = 10;
+ panel1.margins = 10;
+
+ var group1 = panel1.add('group', undefined, { name: 'group1' });
+ group1.orientation = 'row';
+ group1.alignChildren = ['left', 'center'];
+ group1.spacing = 10;
+ group1.margins = [0, 8, 0, 0];
+
+ var group2 = group1.add('group', undefined, { name: 'group2' });
+ group2.orientation = 'column';
+ group2.alignChildren = ['right', 'center'];
+ group2.spacing = 18;
+ group2.margins = 0;
+
+ var statictext1 = group2.add('statictext', undefined, undefined, { name: 'statictext1' });
+ statictext1.text = ui.lines;
+
+ var statictext2 = group2.add('statictext', undefined, undefined, { name: 'statictext2' });
+ statictext2.text = ui.length;
+
+ var group3 = group1.add('group', undefined, { name: 'group3' });
+ group3.orientation = 'column';
+ group3.alignChildren = ['left', 'center'];
+ group3.spacing = 10;
+ group3.margins = 0;
+
+ var edittext1 = group3.add('edittext', undefined, undefined, { name: 'edittext1' });
+ edittext1.text = '1';
+ edittext1.preferredSize.width = 150;
+ edittext1.active = true;
+
+ var group4 = group3.add('group', undefined, { name: 'group4' });
+ group4.orientation = 'row';
+ group4.alignChildren = ['left', 'center'];
+ group4.spacing = 10;
+ group4.margins = 0;
+
+ var edittext2 = group4.add('edittext', undefined, undefined, { name: 'edittext2' });
+ edittext2.text = '10';
+ edittext2.preferredSize.width = 150;
+
+ var statictext3 = group4.add('statictext', undefined, undefined, { name: 'statictext3' });
+ statictext3.text = ruler;
+
+ var group5 = panel1.add('group', undefined, { name: 'group5' });
+ group5.orientation = 'row';
+ group5.alignChildren = ['left', 'center'];
+ group5.spacing = 10;
+ group5.margins = [0, 4, 0, 0];
+
+ var checkbox1 = group5.add('checkbox', undefined, undefined, { name: 'checkbox1' });
+ checkbox1.text = ui.include;
+
+ var panel2 = dialog.add('panel', undefined, undefined, { name: 'panel2' });
+ panel2.text = ui.position;
+ panel2.orientation = 'column';
+ panel2.alignChildren = ['left', 'top'];
+ panel2.spacing = 10;
+ panel2.margins = 10;
+
+ var group6 = panel2.add('group', undefined, { name: 'group6' });
+ group6.orientation = 'row';
+ group6.alignChildren = ['left', 'center'];
+ group6.spacing = 10;
+ group6.margins = [0, 10, 0, 0];
+
+ var checkbox2 = group6.add('checkbox', undefined, undefined, { name: 'checkbox2' });
+ checkbox2.text = ui.flip;
+
+ var checkbox3 = group6.add('checkbox', undefined, undefined, { name: 'checkbox3' });
+ checkbox3.text = ui.middle;
+
+ var group7 = panel2.add('group', undefined, { name: 'group7' });
+ group7.orientation = 'row';
+ group7.alignChildren = ['left', 'center'];
+ group7.spacing = 10;
+ group7.margins = 0;
+
+ var statictext4 = group7.add('statictext', undefined, undefined, { name: 'statictext4' });
+ statictext4.text = ui.margin;
+
+ var edittext3 = group7.add('edittext', undefined, undefined, { name: 'edittext3' });
+ edittext3.text = '0';
+ edittext3.preferredSize.width = 60;
+
+ var statictext5 = group7.add('statictext', undefined, undefined, { name: 'statictext5' });
+ statictext5.text = ruler;
+
+ var group8 = dialog.add('group', undefined, { name: 'group8' });
+ group8.orientation = 'row';
+ group8.alignChildren = ['right', 'center'];
+ group8.spacing = 10;
+ group8.margins = 0;
+
+ // Work around the problem of not being able to undo with the esc key due to localization.
+ var button0 = group8.add('button', undefined, undefined, { name: 'button0' });
+ button0.text = 'Cancel';
+ button0.preferredSize.width = 20;
+ button0.hide();
+
+ var button1 = group8.add('button', undefined, undefined, { name: 'button1' });
+ button1.text = ui.cancel;
+ button1.preferredSize.width = 90;
+
+ var button2 = group8.add('button', undefined, undefined, { name: 'button2' });
+ button2.text = ui.ok;
+ button2.preferredSize.width = 90;
+
+ edittext1.onChanging = function() {
+ preview(dialog, points);
+ }
+
+ edittext2.onChanging = function() {
+ preview(dialog, points);
+ }
+
+ checkbox1.onClick = function() {
+ preview(dialog, points);
+ }
+
+ checkbox2.onClick = function() {
+ preview(dialog, points);
+ }
+
+ checkbox3.onClick = function() {
+ preview(dialog, points);
+ }
+
+ edittext3.onChanging = function() {
+ preview(dialog, points);
+ }
+
+ edittext1.addEventListener('keydown', function(event) {
+ setLineValue(event);
+ preview(dialog, points);
+ });
+
+ edittext2.addEventListener('keydown', function(event) {
+ setLineValue(event);
+ preview(dialog, points);
+ });
+
+ edittext3.addEventListener('keydown', function(event) {
+ setMarginValue(event);
+ preview(dialog, points);
+ });
+
+ statictext1.addEventListener('click', function() {
+ edittext1.active = false;
+ edittext1.active = true;
+ });
+
+ statictext2.addEventListener('click', function() {
+ edittext2.active = false;
+ edittext2.active = true;
+ });
+
+ statictext4.addEventListener('click', function() {
+ edittext3.active = false;
+ edittext3.active = true;
+ });
+
+ button0.onClick = function() {
+ reset(points);
+ dialog.close();
+ }
+
+ button1.onClick = function() {
+ button0.notify('onClick');
+ }
+
+ button2.onClick = function() {
+ dialog.close();
+ }
+
+ dialog.lines = edittext1;
+ dialog.length = edittext2;
+ dialog.include = checkbox1;
+ dialog.flip = checkbox2;
+ dialog.middle = checkbox3;
+ dialog.margin = edittext3;
+ dialog.units = ruler;
+ dialog.ok = button2;
+ return dialog;
+}
+
+
+function setLineValue(event) {
+ var value = getValue(event.target.text);
+ var keyboard = ScriptUI.environment.keyboardState;
+ var step = keyboard.shiftKey ? 5 : 1;
+ if (event.keyName == 'Up') {
+ value += step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+ if (event.keyName == 'Down') {
+ value -= step;
+ if (value < 1) value = 1;
+ event.target.text = value;
+ event.preventDefault();
+ }
+}
+
+
+function setMarginValue(event) {
+ var value = getValue(event.target.text);
+ var keyboard = ScriptUI.environment.keyboardState;
+ var step = keyboard.shiftKey ? 5 : 1;
+ if (event.keyName == 'Up') {
+ value += step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+ if (event.keyName == 'Down') {
+ value -= step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+}
+
+
+function localizeUI() {
+ return {
+ title: {
+ en: 'Draw Normal Line',
+ ja: '法線を描く'
+ },
+ normal: {
+ en: 'Normal Line',
+ ja: '法線'
+ },
+ lines: {
+ en: 'Lines:',
+ ja: '本数:'
+ },
+ length: {
+ en: 'Length:',
+ ja: '長さ:'
+ },
+ include: {
+ en: 'Draw on Selected Anchor Points',
+ ja: '選択アンカーポイントにも描く'
+ },
+ position: {
+ en: 'Position',
+ ja: '位置'
+ },
+ flip: {
+ en: 'Flip',
+ ja: '反転'
+ },
+ middle: {
+ en: 'Middle',
+ ja: '中間'
+ },
+ margin: {
+ en: 'Margin:',
+ ja: '距離:'
+ },
+ cancel: {
+ en: 'Cancel',
+ ja: 'キャンセル'
+ },
+ ok: {
+ en: 'OK',
+ ja: 'OK'
+ }
+ };
+}
diff --git a/scripts/drawRectangle.js b/scripts/drawRectangle.js
index 7b1b36e..c590a37 100755
--- a/scripts/drawRectangle.js
+++ b/scripts/drawRectangle.js
@@ -2,24 +2,25 @@
drawRectangle
Description
- This script draws a rectangle on a selected object.
+ This script draws rectangles around selected objects.
Usage
- 1. Select the path objects, run this script from File > Scripts > Other Script...
+ 1. Select any objects, run this script from File > Scripts > Other Script...
2. Enter a margin value.
- To include stroke width, check the Include stroke width checkbox.
+ 3. To draw a rectangle on each object in the group, check the Ignore Groups checkbox.
+ 4. To include stroke width, check the Use Preview Bounds checkbox.
Notes
The rectangle is drawn with no fill and stroke width.
The units of margin value depend on the ruler units.
- In rare cases, you may not be able to create it.
- In that case, restart Illustrator and run this script again.
+ In rare cases, the script may not work if you continue to use it.
+ In this case, restart Illustrator and try again.
Requirements
- Illustrator CS or higher
+ Illustrator CS4 or higher
Version
- 1.0.0
+ 1.1.0
Homepage
github.com/sky-chaser-high/adobe-illustrator-scripts
@@ -30,43 +31,89 @@
=============================================================================================================================================== */
(function() {
- if (app.documents.length > 0 && app.activeDocument.selection.length > 0) main();
+ if (app.documents.length && isValidVersion()) main();
})();
function main() {
+ var items = app.activeDocument.selection;
+ if (!items.length) return;
+
var dialog = showDialog();
dialog.ok.onClick = function() {
- var margin = getMargin(Number(dialog.margin.text));
- var items = app.activeDocument.selection;
- for (var i = 0; i < items.length; i++) {
- var item = items[i];
- var bounds = dialog.stroke.value ? item.visibleBounds : item.geometricBounds;
- drawRect(bounds, margin);
- item.selected = false;
- }
+ if (dialog.preview.value) return dialog.close();
+ if (dialog.ignore.value) items = getPageItems(items);
+ var margin = getMargin(dialog.margin.text);
+ showShape(items, margin, dialog.stroke.value);
dialog.close();
}
+ dialog.preview.onClick = function() {
+ if (dialog.preview.value) {
+ if (dialog.ignore.value) items = getPageItems(items);
+ var margin = getMargin(dialog.margin.text);
+ showShape(items, margin, dialog.stroke.value);
+ }
+ else {
+ app.undo();
+ }
+ app.redraw();
+ }
+
+ dialog.margin.addEventListener('keydown', function(event) {
+ setIncreaseDecrease(event);
+ preview(dialog, items);
+ });
+
+ dialog.margin.onChanging = function() {
+ preview(dialog, items);
+ }
+
+ dialog.ignore.onClick = function() {
+ preview(dialog, items);
+ }
+
+ dialog.stroke.onClick = function() {
+ preview(dialog, items);
+ }
+
dialog.show();
}
+function preview(dialog, items) {
+ if (!dialog.preview.value) return;
+ app.undo();
+ app.redraw();
+ if (dialog.ignore.value) items = getPageItems(items);
+ var margin = getMargin(dialog.margin.text);
+ showShape(items, margin, dialog.stroke.value);
+ app.redraw();
+}
+
+
+function showShape(items, margin, usePreviewBounds) {
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ var bounds = usePreviewBounds ? item.visibleBounds : item.geometricBounds;
+ drawRect(bounds, margin);
+ item.selected = false;
+ }
+}
+
+
function drawRect(bounds, margin) {
var x1 = bounds[0];
var y1 = bounds[1];
var x2 = bounds[2];
var y2 = bounds[3];
- var width = Math.abs(x2 - x1);
- var height = Math.abs(y2 - y1);
-
- var rect = app.activeDocument.activeLayer.pathItems.rectangle(
- y1 + margin,
- x1 - margin,
- width + (margin * 2),
- height + (margin * 2)
- );
+ var top = y1 + margin;
+ var left = x1 - margin;
+ var width = Math.abs(x2 - x1) + (margin * 2);
+ var height = Math.abs(y2 - y1) + (margin * 2);
+ var layer = app.activeDocument.activeLayer;
+ var rect = layer.pathItems.rectangle(top, left, width, height);
rect.filled = false;
rect.stroked = false;
rect.selected = true;
@@ -74,9 +121,19 @@ function drawRect(bounds, margin) {
function getMargin(value) {
- if (isNaN(value)) return 0;
- var units = getUnits(app.activeDocument.rulerUnits);
- return convertUnits(value + units, 'pt');
+ var margin = getValue(value);
+ var units = getRulerUnits();
+ return convertUnits(margin + units, 'pt');
+}
+
+
+function getValue(text) {
+ var twoByteChar = /[!-~]/g;
+ var value = text.replace(twoByteChar, function(str) {
+ return String.fromCharCode(str.charCodeAt(0) - 0xFEE0);
+ });
+ if (isNaN(value) || !value) return 0;
+ return Number(value);
}
@@ -90,31 +147,101 @@ function convertUnits(value, unit) {
}
-function getUnits(unit) {
- switch (unit) {
- case RulerUnits.Millimeters:
- return 'mm';
- case RulerUnits.Centimeters:
- return 'cm';
- case RulerUnits.Inches:
- return 'in';
- case RulerUnits.Points:
- return 'pt';
- case RulerUnits.Pixels:
- return 'px';
- default:
- return 'pt';
+function getRulerUnits() {
+ var unit = getUnitSymbol();
+ if (!app.documents.length) return unit.pt;
+
+ var document = app.activeDocument;
+ var src = document.fullName;
+ var ruler = document.rulerUnits;
+ try {
+ switch (ruler) {
+ case RulerUnits.Pixels: return unit.px;
+ case RulerUnits.Points: return unit.pt;
+ case RulerUnits.Picas: return unit.pc;
+ case RulerUnits.Inches: return unit.inch;
+ case RulerUnits.Millimeters: return unit.mm;
+ case RulerUnits.Centimeters: return unit.cm;
+
+ case RulerUnits.Feet: return unit.ft;
+ case RulerUnits.Yards: return unit.yd;
+ case RulerUnits.Meters: return unit.meter;
+ }
+ }
+ catch (err) {
+ switch (xmpRulerUnits(src)) {
+ case 'Feet': return unit.ft;
+ case 'Yards': return unit.yd;
+ case 'Meters': return unit.meter;
+ }
}
+ return unit.pt;
+}
+
+
+function xmpRulerUnits(src) {
+ if (!ExternalObject.AdobeXMPScript) {
+ ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
+ }
+ var xmpFile = new XMPFile(src.fsName, XMPConst.FILE_UNKNOWN, XMPConst.OPEN_FOR_READ);
+ var xmpPackets = xmpFile.getXMP();
+ var xmp = new XMPMeta(xmpPackets.serialize());
+
+ var namespace = 'http://ns.adobe.com/xap/1.0/t/pg/';
+ var prop = 'xmpTPg:MaxPageSize';
+ var unit = prop + '/stDim:unit';
+
+ var ruler = xmp.getProperty(namespace, unit).value;
+ return ruler;
+}
+
+
+function getUnitSymbol() {
+ return {
+ px: 'px',
+ pt: 'pt',
+ pc: 'pc',
+ inch: 'in',
+ ft: 'ft',
+ yd: 'yd',
+ mm: 'mm',
+ cm: 'cm',
+ meter: 'm'
+ };
+}
+
+
+function getPageItems(items) {
+ var shapes = [];
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ if (item.typename == 'GroupItem') {
+ shapes = shapes.concat(getPageItems(item.pageItems));
+ }
+ else {
+ shapes.push(item);
+ }
+ }
+ return shapes;
+}
+
+
+function isValidVersion() {
+ var cs4 = 14;
+ var aiVersion = parseInt(app.version);
+ if (aiVersion < cs4) return false;
+ return true;
}
function showDialog() {
$.localize = true;
var ui = localizeUI();
+
var dialog = new Window('dialog');
dialog.text = ui.title;
dialog.orientation = 'column';
- dialog.alignChildren = ['left', 'top'];
+ dialog.alignChildren = ['fill', 'top'];
dialog.spacing = 10;
dialog.margins = 16;
@@ -129,53 +256,98 @@ function showDialog() {
var edittext1 = group1.add('edittext', undefined, undefined, { name: 'edittext1' });
edittext1.text = '0';
- edittext1.preferredSize.width = 180;
+ edittext1.preferredSize.width = 200;
edittext1.active = true;
- var group2 = dialog.add('group', undefined, { name: 'group2' });
- group2.orientation = 'row';
+ var panel1 = dialog.add('panel', undefined, undefined, { name: 'panel1' });
+ panel1.text = ui.options;
+ panel1.orientation = 'column';
+ panel1.alignChildren = ['left', 'top'];
+ panel1.spacing = 10;
+ panel1.margins = 10;
+
+ var group2 = panel1.add('group', undefined, { name: 'group2' });
+ group2.orientation = 'column';
group2.alignChildren = ['left', 'center'];
group2.spacing = 10;
- group2.margins = [0, 5, 0, 0];
+ group2.margins = [0, 10, 0, 0];
var checkbox1 = group2.add('checkbox', undefined, undefined, { name: 'checkbox1' });
- checkbox1.text = ui.stroke;
- checkbox1.value = true;
+ checkbox1.text = ui.ignore;
+
+ var checkbox2 = group2.add('checkbox', undefined, undefined, { name: 'checkbox2' });
+ checkbox2.text = ui.stroke;
var group3 = dialog.add('group', undefined, { name: 'group3' });
group3.orientation = 'row';
- group3.alignChildren = ['right', 'center'];
+ group3.alignChildren = ['left', 'center'];
group3.spacing = 10;
- group3.margins = [0, 10, 0, 0];
- group3.alignment = ['fill', 'top'];
+ group3.margins = 0;
+
+ var checkbox3 = group3.add('checkbox', undefined, undefined, { name: 'checkbox3' });
+ checkbox3.text = ui.preview;
+
+ var group4 = dialog.add('group', undefined, { name: 'group4' });
+ group4.orientation = 'row';
+ group4.alignChildren = ['right', 'center'];
+ group4.spacing = 10;
+ group4.margins = 0;
+
+ // Work around the problem of not being able to undo with the esc key due to localization.
+ var button0 = group4.add('button', undefined, undefined, { name: 'button0' });
+ button0.text = 'Cancel';
+ button0.preferredSize.width = 20;
+ button0.hide();
- var button1 = group3.add('button', undefined, undefined, { name: 'button1' });
+ var button1 = group4.add('button', undefined, undefined, { name: 'button1' });
button1.text = ui.cancel;
button1.preferredSize.width = 90;
- button1.preferredSize.height = 26;
- var button2 = group3.add('button', undefined, undefined, { name: 'button2' });
+ var button2 = group4.add('button', undefined, undefined, { name: 'button2' });
button2.text = ui.ok;
button2.preferredSize.width = 90;
- button2.preferredSize.height = 26;
statictext1.addEventListener('click', function() {
edittext1.active = false;
edittext1.active = true;
});
- button1.onClick = function() {
+ button0.onClick = function() {
+ if (checkbox3.value) app.undo();
dialog.close();
}
+ button1.onClick = function() {
+ button0.notify('onClick');
+ }
+
dialog.margin = edittext1;
- dialog.stroke = checkbox1;
+ dialog.ignore = checkbox1;
+ dialog.stroke = checkbox2;
+ dialog.preview = checkbox3;
dialog.ok = button2;
return dialog;
}
+function setIncreaseDecrease(event) {
+ var value = getValue(event.target.text);
+ var keyboard = ScriptUI.environment.keyboardState;
+ var step = keyboard.shiftKey ? 5 : 1;
+ if (event.keyName == 'Up') {
+ value += step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+ if (event.keyName == 'Down') {
+ value -= step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+}
+
+
function localizeUI() {
return {
title: {
@@ -186,9 +358,21 @@ function localizeUI() {
en: 'Margin:',
ja: 'マージン:'
},
+ options: {
+ en: 'Options',
+ ja: 'オプション'
+ },
+ ignore: {
+ en: 'Ignore Group',
+ ja: 'グループを無視'
+ },
stroke: {
- en: 'Include stroke width',
- ja: '線幅を含む'
+ en: 'Use Preview Bounds',
+ ja: 'プレビュー境界を使用'
+ },
+ preview: {
+ en: 'Preview',
+ ja: 'プレビュー'
},
cancel: {
en: 'Cancel',
diff --git a/scripts/drawShapeOnAnchorPoint.js b/scripts/drawShapeOnAnchorPoint.js
index f507301..30075dd 100755
--- a/scripts/drawShapeOnAnchorPoint.js
+++ b/scripts/drawShapeOnAnchorPoint.js
@@ -5,23 +5,23 @@
This script draws shapes on anchor points.
Usage
- 1. Select the path objects, run this script from File > Scripts > Other Script...
+ 1. Select any path objects, run this script from File > Scripts > Other Script...
2. Select a shape.
3. Enter a shape size.
- 4. Check the Draw Handle Position checkbox if you want to draw the shapes on the handle positions.
+ 4. If you select anchor points with the Direct Selection Tool,
+ choose whether to draw the shape on all anchor points or only on the selected anchor points.
+ 5. Check the Draw Handle Position checkbox if you want to draw the shapes on the handle positions.
Notes
- If you select anchor points with Direct Selection Tool, the shape is drawn only for the selected anchor points.
- The handle position is drawn with a stroke.
The units of shape size depend on the ruler units.
- In rare cases, you may not be able to create it.
- In that case, restart Illustrator and run this script again.
+ In rare cases, the script may not work if you continue to use it.
+ In this case, restart Illustrator and try again.
Requirements
Illustrator CS4 or higher
Version
- 1.0.0
+ 1.1.0
Homepage
github.com/sky-chaser-high/adobe-illustrator-scripts
@@ -32,101 +32,150 @@
=============================================================================================================================================== */
(function() {
- if (app.documents.length > 0 && app.activeDocument.selection.length > 0) main();
+ if (app.documents.length && isValidVersion()) main();
})();
function main() {
- var dialog = showDialog();
+ var items = app.activeDocument.selection;
+ var shapes = getPathItems(items);
+ var points = getSelectedPoints(shapes);
+ if (!points.length) return;
+
+ var dialog = showDialog(points);
dialog.ok.onClick = function() {
- var size = Number(dialog.shapeSize.text);
- var preview = dialog.preview.value;
- if (!preview) draw(dialog.shape, size, dialog.handle.value);
+ if (dialog.preview.value) return dialog.close();
+ var config = getConfiguration(dialog);
+ drawShapes(shapes, config);
dialog.close();
}
dialog.preview.onClick = function() {
- var size = Number(dialog.shapeSize.text);
- var preview = dialog.preview.value;
- if (preview) draw(dialog.shape, size, dialog.handle.value);
- else app.undo();
+ if (dialog.preview.value) {
+ var config = getConfiguration(dialog);
+ drawShapes(shapes, config);
+ }
+ else {
+ reset(points);
+ }
app.redraw();
}
- dialog.show();
-}
+ dialog.shapeSize.addEventListener('keydown', function(event) {
+ setIncreaseDecrease(event);
+ preview(dialog, points);
+ });
+ dialog.shapeSize.onChanging = function() {
+ preview(dialog, points);
+ }
-function draw(shape, size, handle) {
- if (!size) return;
+ dialog.rectangle.onClick = function() {
+ dialog.shapeSize.active = false;
+ dialog.shapeSize.active = true;
+ preview(dialog, points);
+ }
- var layer, name = '__Shapes__';
- if (layerExists(name)) {
- layer = app.activeDocument.layers[name];
- layer.locked = false;
- layer.visible = true;
+ dialog.circle.onClick = function() {
+ dialog.shapeSize.active = false;
+ dialog.shapeSize.active = true;
+ preview(dialog, points);
}
- else {
- layer = createLayer(name);
+
+ dialog.cross.onClick = function() {
+ dialog.shapeSize.active = false;
+ dialog.shapeSize.active = true;
+ preview(dialog, points);
}
- var mode = app.activeDocument.documentColorSpace;
- var color = (mode == DocumentColorSpace.CMYK) ? setCMYKColor(0, 0, 0, 100) : setRGBColor(0, 0, 0);
+ dialog.isAll.onClick = function() {
+ preview(dialog, points);
+ }
+
+ dialog.handle.onClick = function() {
+ preview(dialog, points);
+ }
+
+ dialog.show();
+}
+
+
+function getConfiguration(dialog) {
+ var size = getValue(dialog.shapeSize.text);
+ if (!size) size = 1;
+ return {
+ rectangle: dialog.rectangle.value,
+ circle: dialog.circle.value,
+ cross: dialog.cross.value,
+ size: size,
+ isAll: dialog.isAll.value,
+ handle: dialog.handle.value
+ };
+}
+
+
+function preview(dialog, points) {
+ if (!dialog.preview.value) return;
+ reset(points);
+ app.redraw();
+ var config = getConfiguration(dialog);
+ var items = app.activeDocument.selection;
+ var shapes = getPathItems(items);
+ drawShapes(shapes, config);
+ app.redraw();
+}
- var units = getUnits(app.activeDocument.rulerUnits);
- var dim = convertUnits(size + units, 'pt');
- var items = getPathItems(app.activeDocument.selection);
+function drawShapes(items, config) {
+ var units = getRulerUnits();
+ var size = convertUnits(config.size + units, 'pt');
+
+ var mode = app.activeDocument.documentColorSpace;
+ var color = (mode == DocumentColorSpace.CMYK)
+ ? setCMYKColor(0, 0, 0, 100)
+ : setRGBColor(0, 0, 0);
+
for (var i = 0; i < items.length; i++) {
- var points = getAnchorPoints(items[i], handle);
+ var item = items[i];
+ var points = getAnchorPoints(item, config.handle, config.isAll);
for (var j = 0; j < points.length; j++) {
- if (shape.rect.value) drawRect(dim, color, points[j], layer);
- if (shape.circle.value) drawCircle(dim, color, points[j], layer);
- if (shape.cross.value) drawCross(dim, color, points[j], layer);
+ var point = points[j];
+ if (config.rectangle) drawRect(point, size, color);
+ if (config.circle) drawCircle(point, size, color);
+ if (config.cross) drawCross(point, size, color);
}
}
}
-function drawRect(size, color, point, layer) {
+function drawRect(point, size, color) {
var top = point.y + (size / 2);
var left = point.x - (size / 2);
+ var layer = getLayer('__Shapes__');
var rect = layer.pathItems.rectangle(top, left, size, size);
- if (point.type == 'anchor') {
- rect.stroked = false;
- rect.fillColor = color;
- }
- if (point.type == 'handle') {
- rect.filled = false;
- rect.strokeColor = color;
- rect.strokeWidth = 0.5;
- }
+ rect.stroked = false;
+ rect.fillColor = color;
}
-function drawCircle(size, color, point, layer) {
+function drawCircle(point, size, color) {
var top = point.y + (size / 2);
var left = point.x - (size / 2);
+ var layer = getLayer('__Shapes__');
var circle = layer.pathItems.ellipse(top, left, size, size);
- if (point.type == 'anchor') {
- circle.stroked = false;
- circle.fillColor = color;
- }
- if (point.type == 'handle') {
- circle.filled = false;
- circle.strokeColor = color;
- circle.strokeWidth = 0.5;
- }
+ circle.stroked = false;
+ circle.fillColor = color;
}
-function drawCross(size, color, point, layer) {
+function drawCross(point, size, color) {
var x1 = point.x - (size / 2);
var y1 = point.y + (size / 2);
var x2 = point.x + (size / 2);
var y2 = point.y - (size / 2);
+ var layer = getLayer('__Shapes__');
var group = layer.groupItems.add();
var count = 2;
@@ -143,76 +192,111 @@ function drawCross(size, color, point, layer) {
}
-function getAnchorPoints(item, handle) {
+function getAnchorPoints(item, handle, isAll) {
var ANCHOR = PathPointSelection.ANCHORPOINT;
- var coordinates = [];
- var points = item.selectedPathPoints;
+ var positions = [];
+ var points = item.pathPoints;
for (var i = 0; i < points.length; i++) {
- var target = points[i];
- if (target.selected == ANCHOR) {
- var x = target.anchor[0];
- var y = target.anchor[1];
- coordinates.push({ x: x, y: y, type: 'anchor' });
- if (handle) coordinates = coordinates.concat(getHandle(target));
- }
+ var point = points[i];
+ if (!isAll && point.selected != ANCHOR) continue;
+ var anchor = point.anchor;
+ positions.push({
+ x: anchor[0],
+ y: anchor[1]
+ });
+ if (handle) positions = positions.concat(getHandlePosition(point));
}
- return coordinates;
+ return positions;
}
-function getHandle(point) {
+function getHandlePosition(point) {
var handle = [];
-
- if (hasLeftHandle(point)) {
- var lx = point.leftDirection[0];
- var ly = point.leftDirection[1];
- handle.push({ x: lx, y: ly, type: 'handle' });
+ var anchor = point.anchor;
+ var left = point.leftDirection;
+ var right = point.rightDirection;
+ if (hasHandle(anchor, left)) {
+ handle.push({
+ x: left[0],
+ y: left[1]
+ });
}
-
- if (hasRightHandle(point)) {
- var rx = point.rightDirection[0];
- var ry = point.rightDirection[1];
- handle.push({ x: rx, y: ry, type: 'handle' });
+ if (hasHandle(anchor, right)) {
+ handle.push({
+ x: right[0],
+ y: right[1]
+ });
}
-
return handle;
}
-function hasLeftHandle(point) {
- var ax = point.anchor[0];
- var ay = point.anchor[1];
- var lx = point.leftDirection[0];
- var ly = point.leftDirection[1];
- if (ax == lx && ay == ly) return false;
- return true;
+function hasHandle(anchor, handle) {
+ var x = 0;
+ var y = 1;
+ return anchor[x] != handle[x] || anchor[y] != handle[y];
}
-function hasRightHandle(point) {
- var ax = point.anchor[0];
- var ay = point.anchor[1];
- var rx = point.rightDirection[0];
- var ry = point.rightDirection[1];
- if (ax == rx && ay == ry) return false;
- return true;
+function getSelectedPoints(items) {
+ var ANCHOR = PathPointSelection.ANCHORPOINT;
+ var selection = [];
+ for (var i = 0; i < items.length; i++) {
+ var points = items[i].pathPoints;
+ for (var j = 0; j < points.length; j++) {
+ var point = points[j];
+ if (point.selected != ANCHOR) continue;
+ selection.push(point);
+ }
+ }
+ return selection;
}
function getPathItems(items) {
- var paths = [];
+ var shapes = [];
for (var i = 0; i < items.length; i++) {
- if (items[i].typename == 'PathItem') {
- paths.push(items[i]);
+ var item = items[i];
+ if (item.typename == 'PathItem') {
+ shapes.push(item);
}
- else if (items[i].typename == 'GroupItem') {
- paths = paths.concat(getPathItems(items[i].pageItems));
+ if (item.typename == 'GroupItem') {
+ shapes = shapes.concat(getPathItems(item.pageItems));
}
- else if (items[i].typename == 'CompoundPathItem') {
- paths = paths.concat(getPathItems(items[i].pathItems));
+ if (item.typename == 'CompoundPathItem') {
+ shapes = shapes.concat(getPathItems(item.pathItems));
}
}
- return paths;
+ return shapes;
+}
+
+
+function reset(items) {
+ app.undo();
+ var ANCHOR = PathPointSelection.ANCHORPOINT;
+ var NOSELECTION = PathPointSelection.NOSELECTION;
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ var points = item.parent.pathPoints;
+ for (var j = 0; j < points.length; j++) {
+ var point = points[j];
+ point.selected = NOSELECTION;
+ }
+ }
+ for (var i = 0; i < items.length; i++) {
+ var point = items[i];
+ point.selected = ANCHOR;
+ }
+}
+
+
+function getValue(text) {
+ var twoByteChar = /[!-~]/g;
+ var value = text.replace(twoByteChar, function(str) {
+ return String.fromCharCode(str.charCodeAt(0) - 0xFEE0);
+ });
+ if (isNaN(value) || !value) return 0;
+ return Number(value);
}
@@ -226,15 +310,78 @@ function convertUnits(value, unit) {
}
-function getUnits(unit) {
- switch (unit) {
- case RulerUnits.Millimeters: return 'mm';
- case RulerUnits.Centimeters: return 'cm';
- case RulerUnits.Inches: return 'in';
- case RulerUnits.Points: return 'pt';
- case RulerUnits.Pixels: return 'px';
- default: return 'pt';
+function getRulerUnits() {
+ var unit = getUnitSymbol();
+ if (!app.documents.length) return unit.pt;
+
+ var document = app.activeDocument;
+ var src = document.fullName;
+ var ruler = document.rulerUnits;
+ try {
+ switch (ruler) {
+ case RulerUnits.Pixels: return unit.px;
+ case RulerUnits.Points: return unit.pt;
+ case RulerUnits.Picas: return unit.pc;
+ case RulerUnits.Inches: return unit.inch;
+ case RulerUnits.Millimeters: return unit.mm;
+ case RulerUnits.Centimeters: return unit.cm;
+
+ case RulerUnits.Feet: return unit.ft;
+ case RulerUnits.Yards: return unit.yd;
+ case RulerUnits.Meters: return unit.meter;
+ }
+ }
+ catch (err) {
+ switch (xmpRulerUnits(src)) {
+ case 'Feet': return unit.ft;
+ case 'Yards': return unit.yd;
+ case 'Meters': return unit.meter;
+ }
}
+ return unit.pt;
+}
+
+
+function xmpRulerUnits(src) {
+ if (!ExternalObject.AdobeXMPScript) {
+ ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
+ }
+ var xmpFile = new XMPFile(src.fsName, XMPConst.FILE_UNKNOWN, XMPConst.OPEN_FOR_READ);
+ var xmpPackets = xmpFile.getXMP();
+ var xmp = new XMPMeta(xmpPackets.serialize());
+
+ var namespace = 'http://ns.adobe.com/xap/1.0/t/pg/';
+ var prop = 'xmpTPg:MaxPageSize';
+ var unit = prop + '/stDim:unit';
+
+ var ruler = xmp.getProperty(namespace, unit).value;
+ return ruler;
+}
+
+
+function getUnitSymbol() {
+ return {
+ px: 'px',
+ pt: 'pt',
+ pc: 'pc',
+ inch: 'in',
+ ft: 'ft',
+ yd: 'yd',
+ mm: 'mm',
+ cm: 'cm',
+ meter: 'm'
+ };
+}
+
+
+function getLayer(name) {
+ if (layerExists(name)) {
+ var layer = app.activeDocument.layers[name];
+ layer.locked = false;
+ layer.visible = true;
+ return layer;
+ }
+ return createLayer(name);
}
@@ -276,21 +423,37 @@ function setRGBColor(r, g, b) {
}
-function showDialog() {
+function isValidVersion() {
+ var cs4 = 14;
+ var aiVersion = parseInt(app.version);
+ if (aiVersion < cs4) return false;
+ return true;
+}
+
+
+function showDialog(points) {
$.localize = true;
var ui = localizeUI();
+
var dialog = new Window('dialog');
dialog.text = ui.title;
dialog.orientation = 'column';
- dialog.alignChildren = ['left', 'top'];
+ dialog.alignChildren = ['fill', 'top'];
dialog.spacing = 10;
dialog.margins = 16;
- var group1 = dialog.add('group', undefined, { name: 'group1' });
+ var panel1 = dialog.add('panel', undefined, undefined, { name: 'panel1' });
+ panel1.text = ui.shape;
+ panel1.orientation = 'column';
+ panel1.alignChildren = ['fill', 'top'];
+ panel1.spacing = 10;
+ panel1.margins = 10;
+
+ var group1 = panel1.add('group', undefined, { name: 'group1' });
group1.orientation = 'row';
group1.alignChildren = ['left', 'center'];
group1.spacing = 10;
- group1.margins = 0;
+ group1.margins = [0, 4, 0, 0];
var group2 = group1.add('group', undefined, { name: 'group2' });
group2.orientation = 'column';
@@ -299,7 +462,7 @@ function showDialog() {
group2.margins = 0;
var statictext1 = group2.add('statictext', undefined, undefined, { name: 'statictext1' });
- statictext1.text = ui.shape;
+ statictext1.text = ui.type;
var statictext2 = group2.add('statictext', undefined, undefined, { name: 'statictext2' });
statictext2.text = ui.size;
@@ -308,13 +471,13 @@ function showDialog() {
group3.orientation = 'column';
group3.alignChildren = ['fill', 'center'];
group3.spacing = 10;
- group3.margins = 0;
+ group3.margins = [0, 6, 0, 0];
var group4 = group3.add('group', undefined, { name: 'group4' });
group4.orientation = 'row';
group4.alignChildren = ['left', 'center'];
group4.spacing = 10;
- group4.margins = [0, 4, 0, 0];
+ group4.margins = 0;
var radiobutton1 = group4.add('radiobutton', undefined, undefined, { name: 'radiobutton1' });
radiobutton1.text = ui.rect;
@@ -327,62 +490,102 @@ function showDialog() {
radiobutton3.text = ui.cross;
var edittext1 = group3.add('edittext', undefined, undefined, { name: 'edittext1' });
- edittext1.text = '2';
+ edittext1.text = '1';
edittext1.active = true;
- var group5 = dialog.add('group', undefined, { name: 'group5' });
+ var panel2 = dialog.add('panel', undefined, undefined, { name: 'panel2' });
+ panel2.text = ui.options;
+ panel2.orientation = 'column';
+ panel2.alignChildren = ['fill', 'top'];
+ panel2.spacing = 10;
+ panel2.margins = 10;
+
+ var group5 = panel2.add('group', undefined, { name: 'group5' });
group5.orientation = 'column';
group5.alignChildren = ['left', 'center'];
group5.spacing = 10;
- group5.margins = [0, 6, 0, 0];
+ group5.margins = [0, 10, 0, 0];
var checkbox1 = group5.add('checkbox', undefined, undefined, { name: 'checkbox1' });
- checkbox1.text = ui.handle;
+ checkbox1.text = ui.all;
+ checkbox1.value = true;
var checkbox2 = group5.add('checkbox', undefined, undefined, { name: 'checkbox2' });
- checkbox2.text = ui.preview;
+ checkbox2.text = ui.handle;
var group6 = dialog.add('group', undefined, { name: 'group6' });
group6.orientation = 'row';
- group6.alignChildren = ['right', 'center'];
+ group6.alignChildren = ['left', 'center'];
group6.spacing = 10;
- group6.margins = [0, 10, 0, 0];
- group6.alignment = ['fill', 'top'];
+ group6.margins = 0;
+
+ var checkbox3 = group6.add('checkbox', undefined, undefined, { name: 'checkbox3' });
+ checkbox3.text = ui.preview;
- var button1 = group6.add('button', undefined, undefined, { name: 'button1' });
+ var group7 = dialog.add('group', undefined, { name: 'group7' });
+ group7.orientation = 'row';
+ group7.alignChildren = ['right', 'center'];
+ group7.spacing = 10;
+ group7.margins = 0;
+
+ // Work around the problem of not being able to undo with the esc key due to localization.
+ var button0 = group7.add('button', undefined, undefined, { name: 'button0' });
+ button0.text = 'Cancel';
+ button0.preferredSize.width = 20;
+ button0.hide();
+
+ var button1 = group7.add('button', undefined, undefined, { name: 'button1' });
button1.text = ui.cancel;
button1.preferredSize.width = 90;
- button1.preferredSize.height = 26;
- var button2 = group6.add('button', undefined, undefined, { name: 'button2' });
+ var button2 = group7.add('button', undefined, undefined, { name: 'button2' });
button2.text = ui.ok;
button2.preferredSize.width = 90;
- button2.preferredSize.height = 26;
statictext2.addEventListener('click', function() {
edittext1.active = false;
edittext1.active = true;
});
- button1.onClick = function() {
- if (checkbox2.value) app.undo();
+ button0.onClick = function() {
+ if (checkbox3.value) reset(points);
dialog.close();
}
- dialog.shape = {
- rect: radiobutton1,
- circle: radiobutton2,
- cross: radiobutton3
- };
+ button1.onClick = function() {
+ button0.notify('onClick');
+ }
+
+ dialog.rectangle = radiobutton1,
+ dialog.circle = radiobutton2,
+ dialog.cross = radiobutton3
dialog.shapeSize = edittext1;
- dialog.handle = checkbox1;
- dialog.preview = checkbox2;
+ dialog.isAll = checkbox1;
+ dialog.handle = checkbox2;
+ dialog.preview = checkbox3;
dialog.ok = button2;
-
return dialog;
}
+function setIncreaseDecrease(event) {
+ var value = getValue(event.target.text);
+ var keyboard = ScriptUI.environment.keyboardState;
+ var step = keyboard.shiftKey ? 5 : 1;
+ if (event.keyName == 'Up') {
+ value += step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+ if (event.keyName == 'Down') {
+ value -= step;
+ if (value < 1) value = 1;
+ event.target.text = value;
+ event.preventDefault();
+ }
+}
+
+
function localizeUI() {
return {
title: {
@@ -390,11 +593,15 @@ function localizeUI() {
ja: 'アンカーポイントに図形を描く'
},
shape: {
- en: 'Shape:',
- ja: '形状:'
+ en: 'Shape',
+ ja: '図形'
+ },
+ type: {
+ en: 'Type:',
+ ja: '種類:'
},
rect: {
- en: 'Rect',
+ en: 'Rectangle',
ja: '矩形'
},
circle: {
@@ -409,6 +616,14 @@ function localizeUI() {
en: 'Size:',
ja: 'サイズ:'
},
+ options: {
+ en: 'Options',
+ ja: 'オプション'
+ },
+ all: {
+ en: 'All Anchor Points',
+ ja: 'すべてのアンカーポイント'
+ },
handle: {
en: 'Draw Handle Position',
ja: 'ハンドル位置も描く'
diff --git a/scripts/drawShapeParallelToPathSegment.js b/scripts/drawShapeParallelToPathSegment.js
new file mode 100755
index 0000000..f61f352
--- /dev/null
+++ b/scripts/drawShapeParallelToPathSegment.js
@@ -0,0 +1,674 @@
+/* ===============================================================================================================================================
+ drawShapeParallelToPathSegment
+
+ Description
+ This script draws a shape parallel to a straight segment or a line connecting two anchor points.
+
+ Usage
+ 1. Select two anchor points with the Direct Selection Tool, run this script from File > Scripts > Other Script...
+ 2. Select a Square, Rectangle or Ellipse.
+ 3. If you select the Rectangle or Ellipse, enter width and height values.
+ 4. Check the Flip checkbox reverses the drawing position.
+ 5. Check the Middle checkbox to draw in the middle of the path segment.
+ 6. Enter a value of the margin will space them from the path segment.
+
+ Notes
+ Curves are not supported.
+ Anchor points for type on a path and area type are also supported.
+ The units of the Width, Height and Margin value depend on the ruler units.
+ In rare cases, the script may not work if you continue to use it.
+ In this case, restart Illustrator and try again.
+
+ Requirements
+ Illustrator CS4 or higher
+
+ Version
+ 1.0.0
+
+ Homepage
+ github.com/sky-chaser-high/adobe-illustrator-scripts
+
+ License
+ Released under the MIT license.
+ https://opensource.org/licenses/mit-license.php
+ =============================================================================================================================================== */
+
+(function() {
+ if (app.documents.length && isValidVersion()) main();
+})();
+
+
+function main() {
+ var items = app.activeDocument.selection;
+ var shapes = getPathItems(items);
+ var texts = getTextPathItems();
+ var points = getSelectedAnchorPoints(shapes.concat(texts));
+ if (points.length != 2) return;
+
+ var p1 = setPoint(points[0]);
+ var p2 = setPoint(points[1]);
+ var length = getLength(p1, p2);
+ var shape = {
+ ellipse: false,
+ width: length,
+ height: length
+ }
+ var margin = 0;
+ var flip = false;
+ var middle = false;
+
+ drawShape(points, shape, margin, flip, middle);
+ app.redraw();
+
+ var dialog = showDialog(points);
+ dialog.show();
+}
+
+
+function getConfiguration(dialog) {
+ var width = getValue(dialog.shape.width.text);
+ var height = getValue(dialog.shape.height.text);
+ var flip = (dialog.flip.value) ? true : false;
+ var middle = (dialog.middle.value) ? true : false;
+ var margin = getValue(dialog.margin.text);
+ var units = dialog.units;
+ return {
+ shape: {
+ ellipse: dialog.shape.ellipse.value,
+ width: convertUnits(width + units, 'pt'),
+ height: convertUnits(height + units, 'pt')
+ },
+ flip: flip,
+ middle: middle,
+ margin: convertUnits(margin + units, 'pt')
+ };
+}
+
+
+function preview(dialog, points) {
+ reset(points);
+ var config = getConfiguration(dialog);
+ drawShape(points, config.shape, config.margin, config.flip, config.middle);
+ app.redraw();
+}
+
+
+function drawShape(points, shape, margin, isFlip, isMiddle) {
+ var p1 = isFlip ? setPoint(points[1]) : setPoint(points[0]);
+ var p2 = isFlip ? setPoint(points[0]) : setPoint(points[1]);
+
+ var position = getPosition(p1, p2, shape.width);
+ var rad = getAngle(p1, p2);
+ var deg = rad * 180 / Math.PI;
+
+ var layer = app.activeDocument.activeLayer;
+ var rectangle = shape.ellipse
+ ? layer.pathItems.ellipse(position.top, position.left, shape.width, shape.height)
+ : layer.pathItems.rectangle(position.top, position.left, shape.width, shape.height);
+ rectangle.filled = false;
+ rectangle.stroked = true;
+ rectangle.strokeWidth = 1;
+
+ rectangle.rotate(deg, true, true, true, true, Transformation.TOPLEFT);
+ if (isMiddle) {
+ var pathPoints = rectangle.pathPoints;
+ var a1 = shape.ellipse ? pathPoints[3] : pathPoints[0];
+ var a2 = shape.ellipse ? pathPoints[1] : pathPoints[1];
+ var center = getCenter(a1.anchor, a2.anchor);
+ rectangle.translate(center.x, center.y);
+ }
+ if (margin) {
+ var angle = rad - Math.PI / 2;
+ var distance = getDistance(margin, angle);
+ rectangle.translate(distance.x, distance.y);
+ }
+}
+
+
+function getPosition(point1, point2, length) {
+ var width = point2.x - point1.x;
+ var height = point2.y - point1.y;
+ var rad = getAngle(point1, point2);
+ var distance = getDistance(length, rad);
+ return {
+ left: point1.x + (width / 2) - (distance.x / 2),
+ top: point1.y + (height / 2) - (distance.y / 2)
+ };
+}
+
+
+function getCenter(point1, point2) {
+ var p1 = {
+ x: point1[0],
+ y: point1[1]
+ };
+ var p2 = {
+ x: point2[0],
+ y: point2[1]
+ };
+ var x = (p2.x - p1.x) / 2;
+ var y = (p2.y - p1.y) / 2;
+ return {
+ x: x,
+ y: y
+ };
+}
+
+
+function getDistance(value, angle) {
+ var x = value * Math.cos(angle);
+ var y = value * Math.sin(angle);
+ return {
+ x: x,
+ y: y
+ };
+}
+
+
+function getLength(point1, point2) {
+ var width = point2.x - point1.x;
+ var height = point2.y - point1.y;
+ var sq = 2;
+ var length = Math.sqrt(Math.pow(width, sq) + Math.pow(height, sq));
+ return length;
+}
+
+
+function getAngle(point1, point2) {
+ var width = point2.x - point1.x;
+ var height = point2.y - point1.y;
+ return Math.atan2(height, width);
+}
+
+
+function setPoint(item) {
+ return {
+ x: item.anchor[0],
+ y: item.anchor[1]
+ };
+}
+
+
+function getSelectedAnchorPoints(shapes) {
+ var ANCHOR = PathPointSelection.ANCHORPOINT;
+ var anchors = [];
+ for (var i = 0; i < shapes.length; i++) {
+ var points = shapes[i].pathPoints;
+ for (var j = 0; j < points.length; j++) {
+ var point = points[j];
+ if (point.selected != ANCHOR) continue;
+ anchors.push(point);
+ }
+ }
+ return anchors;
+}
+
+
+function getPathItems(items) {
+ var shapes = [];
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ if (item.typename == 'PathItem' || item.typename == 'CompoundPathItem') {
+ shapes.push(item);
+ }
+ if (item.typename == 'GroupItem') {
+ shapes = shapes.concat(getPathItems(item.pageItems));
+ }
+ }
+ return shapes;
+}
+
+
+function getTextPathItems() {
+ var items = [];
+ var texts = app.activeDocument.textFrames;
+ for (var i = 0; i < texts.length; i++) {
+ var text = texts[i];
+ if (text.selected && text.kind != TextType.POINTTEXT) {
+ items.push(text.textPath);
+ }
+ }
+ return items;
+}
+
+
+function reset(items) {
+ app.undo();
+ var ANCHOR = PathPointSelection.ANCHORPOINT;
+ var NOSELECTION = PathPointSelection.NOSELECTION;
+ for (var i = 0; i < items.length; i++) {
+ var points = items[i].parent.pathPoints;
+ for (var j = 0; j < points.length; j++) {
+ var point = points[j];
+ point.selected = NOSELECTION;
+ }
+ }
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ item.selected = ANCHOR;
+ }
+}
+
+
+function getValue(text) {
+ var twoByteChar = /[!-~]/g;
+ var value = text.replace(twoByteChar, function(str) {
+ return String.fromCharCode(str.charCodeAt(0) - 0xFEE0);
+ });
+ if (isNaN(value) || !value) return 0;
+ return Number(value);
+}
+
+
+function convertUnits(value, unit) {
+ try {
+ return Number(UnitValue(value).as(unit));
+ }
+ catch (err) {
+ return Number(UnitValue('1pt').as('pt'));
+ }
+}
+
+
+function getRulerUnits() {
+ var unit = getUnitSymbol();
+ if (!app.documents.length) return unit.pt;
+
+ var document = app.activeDocument;
+ var src = document.fullName;
+ var ruler = document.rulerUnits;
+ try {
+ switch (ruler) {
+ case RulerUnits.Pixels: return unit.px;
+ case RulerUnits.Points: return unit.pt;
+ case RulerUnits.Picas: return unit.pc;
+ case RulerUnits.Inches: return unit.inch;
+ case RulerUnits.Millimeters: return unit.mm;
+ case RulerUnits.Centimeters: return unit.cm;
+
+ case RulerUnits.Feet: return unit.ft;
+ case RulerUnits.Yards: return unit.yd;
+ case RulerUnits.Meters: return unit.meter;
+ }
+ }
+ catch (err) {
+ switch (xmpRulerUnits(src)) {
+ case 'Feet': return unit.ft;
+ case 'Yards': return unit.yd;
+ case 'Meters': return unit.meter;
+ }
+ }
+ return unit.pt;
+}
+
+
+function xmpRulerUnits(src) {
+ if (!ExternalObject.AdobeXMPScript) {
+ ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
+ }
+ var xmpFile = new XMPFile(src.fsName, XMPConst.FILE_UNKNOWN, XMPConst.OPEN_FOR_READ);
+ var xmpPackets = xmpFile.getXMP();
+ var xmp = new XMPMeta(xmpPackets.serialize());
+
+ var namespace = 'http://ns.adobe.com/xap/1.0/t/pg/';
+ var prop = 'xmpTPg:MaxPageSize';
+ var unit = prop + '/stDim:unit';
+
+ var ruler = xmp.getProperty(namespace, unit).value;
+ return ruler;
+}
+
+
+function getUnitSymbol() {
+ return {
+ px: 'px',
+ pt: 'pt',
+ pc: 'pc',
+ inch: 'in',
+ ft: 'ft',
+ yd: 'yd',
+ mm: 'mm',
+ cm: 'cm',
+ meter: 'm'
+ };
+}
+
+
+function isValidVersion() {
+ var cs4 = 14;
+ var aiVersion = parseInt(app.version);
+ if (aiVersion < cs4) return false;
+ return true;
+}
+
+
+function showDialog(points) {
+ $.localize = true;
+ var ui = localizeUI();
+ var ruler = getRulerUnits();
+ var p1 = setPoint(points[0]);
+ var p2 = setPoint(points[1]);
+ var length = getLength(p1, p2);
+ length = convertUnits(length + 'pt', ruler);
+
+ var dialog = new Window('dialog');
+ dialog.text = ui.title;
+ dialog.orientation = 'column';
+ dialog.alignChildren = ['fill', 'top'];
+ dialog.spacing = 10;
+ dialog.margins = 16;
+
+ var panel1 = dialog.add('panel', undefined, undefined, { name: 'panel1' });
+ panel1.text = ui.shape;
+ panel1.orientation = 'column';
+ panel1.alignChildren = ['left', 'top'];
+ panel1.spacing = 10;
+ panel1.margins = 10;
+
+ var group1 = panel1.add('group', undefined, { name: 'group1' });
+ group1.orientation = 'row';
+ group1.alignChildren = ['left', 'center'];
+ group1.spacing = 10;
+ group1.margins = [0, 8, 0, 0];
+
+ var radiobutton1 = group1.add('radiobutton', undefined, undefined, { name: 'radiobutton1' });
+ radiobutton1.text = ui.square;
+ radiobutton1.value = true;
+
+ var radiobutton2 = group1.add('radiobutton', undefined, undefined, { name: 'radiobutton2' });
+ radiobutton2.text = ui.rectangle;
+
+ var radiobutton3 = group1.add('radiobutton', undefined, undefined, { name: 'radiobutton3' });
+ radiobutton3.text = ui.ellipse;
+
+ var group2 = panel1.add('group', undefined, { name: 'group2' });
+ group2.orientation = 'row';
+ group2.alignChildren = ['left', 'center'];
+ group2.spacing = 10;
+ group2.margins = 0;
+ group2.enabled = false;
+
+ var group3 = group2.add('group', undefined, { name: 'group3' });
+ group3.orientation = 'column';
+ group3.alignChildren = ['right', 'center'];
+ group3.spacing = 18;
+ group3.margins = 0;
+
+ var statictext1 = group3.add('statictext', undefined, undefined, { name: 'statictext1' });
+ statictext1.text = ui.width;
+
+ var statictext2 = group3.add('statictext', undefined, undefined, { name: 'statictext2' });
+ statictext2.text = ui.height;
+
+ var group4 = group2.add('group', undefined, { name: 'group4' });
+ group4.orientation = 'column';
+ group4.alignChildren = ['left', 'center'];
+ group4.spacing = 10;
+ group4.margins = 0;
+
+ var edittext1 = group4.add('edittext', undefined, undefined, { name: 'edittext1' });
+ edittext1.text = length;
+ edittext1.preferredSize.width = 150;
+
+ var edittext2 = group4.add('edittext', undefined, undefined, { name: 'edittext2' });
+ edittext2.text = length;
+ edittext2.preferredSize.width = 150;
+
+ var group5 = group2.add('group', undefined, { name: 'group5' });
+ group5.orientation = 'column';
+ group5.alignChildren = ['left', 'center'];
+ group5.spacing = 18;
+ group5.margins = 0;
+
+ var statictext3 = group5.add('statictext', undefined, undefined, { name: 'statictext3' });
+ statictext3.text = ruler;
+
+ var statictext4 = group5.add('statictext', undefined, undefined, { name: 'statictext4' });
+ statictext4.text = ruler;
+
+ var panel2 = dialog.add('panel', undefined, undefined, { name: 'panel2' });
+ panel2.text = ui.position;
+ panel2.orientation = 'column';
+ panel2.alignChildren = ['left', 'top'];
+ panel2.spacing = 10;
+ panel2.margins = 10;
+
+ var group6 = panel2.add('group', undefined, { name: 'group6' });
+ group6.orientation = 'row';
+ group6.alignChildren = ['left', 'center'];
+ group6.spacing = 10;
+ group6.margins = [0, 10, 0, 0];
+
+ var checkbox1 = group6.add('checkbox', undefined, undefined, { name: 'checkbox1' });
+ checkbox1.text = ui.flip;
+
+ var checkbox2 = group6.add('checkbox', undefined, undefined, { name: 'checkbox2' });
+ checkbox2.text = ui.middle;
+
+ var group7 = panel2.add('group', undefined, { name: 'group7' });
+ group7.orientation = 'row';
+ group7.alignChildren = ['left', 'center'];
+ group7.spacing = 10;
+ group7.margins = 0;
+
+ var statictext5 = group7.add('statictext', undefined, undefined, { name: 'statictext5' });
+ statictext5.text = ui.margin;
+
+ var edittext3 = group7.add('edittext', undefined, undefined, { name: 'edittext3' });
+ edittext3.text = '0';
+ edittext3.preferredSize.width = 60;
+
+ var statictext6 = group7.add('statictext', undefined, undefined, { name: 'statictext6' });
+ statictext6.text = ruler;
+
+ var group8 = dialog.add('group', undefined, { name: 'group8' });
+ group8.orientation = 'row';
+ group8.alignChildren = ['right', 'center'];
+ group8.spacing = 10;
+ group8.margins = 0;
+
+ // Work around the problem of not being able to undo with the esc key due to localization.
+ var button0 = group8.add('button', undefined, undefined, { name: 'button0' });
+ button0.text = 'Cancel';
+ button0.preferredSize.width = 20;
+ button0.hide();
+
+ var button1 = group8.add('button', undefined, undefined, { name: 'button1' });
+ button1.text = ui.cancel;
+ button1.preferredSize.width = 90;
+
+ var button2 = group8.add('button', undefined, undefined, { name: 'button2' });
+ button2.text = ui.ok;
+ button2.preferredSize.width = 90;
+
+ radiobutton1.onClick = function() {
+ group2.enabled = false;
+ edittext1.text = length;
+ edittext2.text = length;
+ preview(dialog, points);
+ }
+
+ radiobutton2.onClick = function() {
+ group2.enabled = true;
+ edittext1.active = false;
+ edittext1.active = true;
+ preview(dialog, points);
+ }
+
+ radiobutton3.onClick = function() {
+ group2.enabled = true;
+ edittext1.active = false;
+ edittext1.active = true;
+ preview(dialog, points);
+ }
+
+ edittext1.onChanging = function() {
+ preview(dialog, points);
+ }
+
+ edittext2.onChanging = function() {
+ preview(dialog, points);
+ }
+
+ checkbox1.onClick = function() {
+ preview(dialog, points);
+ }
+
+ checkbox2.onClick = function() {
+ preview(dialog, points);
+ }
+
+ edittext3.onChanging = function() {
+ preview(dialog, points);
+ }
+
+ edittext1.addEventListener('keydown', function(event) {
+ setSizeValue(event);
+ preview(dialog, points);
+ });
+
+ edittext2.addEventListener('keydown', function(event) {
+ setSizeValue(event);
+ preview(dialog, points);
+ });
+
+ edittext3.addEventListener('keydown', function(event) {
+ setMarginValue(event);
+ preview(dialog, points);
+ });
+
+ statictext1.addEventListener('click', function() {
+ edittext1.active = false;
+ edittext1.active = true;
+ });
+
+ statictext2.addEventListener('click', function() {
+ edittext2.active = false;
+ edittext2.active = true;
+ });
+
+ statictext5.addEventListener('click', function() {
+ edittext3.active = false;
+ edittext3.active = true;
+ });
+
+ button0.onClick = function() {
+ reset(points);
+ dialog.close();
+ }
+
+ button1.onClick = function() {
+ button0.notify('onClick');
+ }
+
+ button2.onClick = function() {
+ dialog.close();
+ }
+
+ dialog.shape = {
+ square: radiobutton1,
+ rectangle: radiobutton2,
+ ellipse: radiobutton3,
+ size: group2,
+ width: edittext1,
+ height: edittext2
+ };
+ dialog.flip = checkbox1;
+ dialog.middle = checkbox2;
+ dialog.margin = edittext3;
+ dialog.units = ruler;
+ return dialog;
+}
+
+
+function setSizeValue(event) {
+ var value = getValue(event.target.text);
+ var keyboard = ScriptUI.environment.keyboardState;
+ var step = keyboard.shiftKey ? 5 : 1;
+ if (event.keyName == 'Up') {
+ value += step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+ if (event.keyName == 'Down') {
+ value -= step;
+ if (value < 1) value = 1;
+ event.target.text = value;
+ event.preventDefault();
+ }
+}
+
+
+function setMarginValue(event) {
+ var value = getValue(event.target.text);
+ var keyboard = ScriptUI.environment.keyboardState;
+ var step = keyboard.shiftKey ? 5 : 1;
+ if (event.keyName == 'Up') {
+ value += step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+ if (event.keyName == 'Down') {
+ value -= step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+}
+
+
+function localizeUI() {
+ return {
+ title: {
+ en: 'Draw Shape Parallel to Path Segment',
+ ja: '直線に並行な図形を描く'
+ },
+ shape: {
+ en: 'Shape',
+ ja: '図形'
+ },
+ square: {
+ en: 'Square',
+ ja: '正方形'
+ },
+ rectangle: {
+ en: 'Rectangle',
+ ja: '長方形'
+ },
+ ellipse: {
+ en: 'Ellipse',
+ ja: '楕円'
+ },
+ width: {
+ en: 'Width:',
+ ja: '幅:'
+ },
+ height: {
+ en: 'Height:',
+ ja: '高さ:'
+ },
+ position: {
+ en: 'Position',
+ ja: '位置'
+ },
+ flip: {
+ en: 'Flip',
+ ja: '反転'
+ },
+ middle: {
+ en: 'Middle',
+ ja: '中間'
+ },
+ margin: {
+ en: 'Margin:',
+ ja: '間隔:'
+ },
+ cancel: {
+ en: 'Cancel',
+ ja: 'キャンセル'
+ },
+ ok: {
+ en: 'OK',
+ ja: 'OK'
+ }
+ };
+}
diff --git a/scripts/extendHandle.js b/scripts/extendHandle.js
index 87f5ba7..26592c5 100755
--- a/scripts/extendHandle.js
+++ b/scripts/extendHandle.js
@@ -5,7 +5,7 @@
This script extends and shrinks handles. It also changes the angle.
Usage
- 1. Select one or two anchor points with Direct Selection Tool, run this script from File > Scripts > Other Script...
+ 1. Select one or two anchor points with the Direct Selection Tool, run this script from File > Scripts > Other Script...
2. Enter a positive value in the Distance fields to extend or a negative value to shrink.
3. Enter a positive value in the Angle fields will rotate counterclockwise. Enter a negative value clockwise.
@@ -20,7 +20,7 @@
Illustrator CS4 or higher
Version
- 1.1.0
+ 1.2.0
Homepage
github.com/sky-chaser-high/adobe-illustrator-scripts
@@ -31,7 +31,7 @@
=============================================================================================================================================== */
(function() {
- if (app.documents.length > 0) main();
+ if (app.documents.length && isValidVersion()) main();
})();
@@ -49,17 +49,21 @@ function main() {
var dialog = showDialog(points, showHandles);
dialog.ok.onClick = function() {
- if (dialog.preview.value) reset(points);
- var config = getConfig(dialog);
- extendHandle(points[0], points[1], config.distance, config.angle);
+ if (dialog.preview.value) return dialog.close();
+ var config = getConfiguration(dialog);
+ var p1 = points[0];
+ var p2 = points[1];
+ extendHandle(p1, p2, config.distance, config.angle);
if (!showHandles) app.preferences.setBooleanPreference('showDirectionHandles', false);
dialog.close();
}
dialog.preview.onClick = function() {
if (dialog.preview.value) {
- var config = getConfig(dialog);
- extendHandle(points[0], points[1], config.distance, config.angle);
+ var config = getConfiguration(dialog);
+ var p1 = points[0];
+ var p2 = points[1];
+ extendHandle(p1, p2, config.distance, config.angle);
}
else {
reset(points);
@@ -107,17 +111,17 @@ function extendHandle(p1, p2, distance, rotation) {
function getAngle(p1, p2) {
- var adjacent = p2.x - p1.x;
- var opposite = p2.y - p1.y;
- return Math.atan2(opposite, adjacent);
+ var width = p2.x - p1.x;
+ var height = p2.y - p1.y;
+ return Math.atan2(height, width);
}
function getDistance(p1, p2) {
- var adjacent = p2.x - p1.x;
- var opposite = p2.y - p1.y;
- var hypotenuse = Math.sqrt(Math.pow(adjacent, 2) + Math.pow(opposite, 2));
- return hypotenuse;
+ var width = p2.x - p1.x;
+ var height = p2.y - p1.y;
+ var sq = 2;
+ return Math.sqrt(Math.pow(width, sq) + Math.pow(height, sq));
}
@@ -179,13 +183,11 @@ function getPathItems(items) {
function getTextPathItems() {
- var AREA = TextType.AREATEXT;
- var PATH = TextType.PATHTEXT;
var items = [];
var texts = app.activeDocument.textFrames;
for (var i = 0; i < texts.length; i++) {
var text = texts[i];
- if (text.selected && (text.kind == AREA || text.kind == PATH)) {
+ if (text.selected && text.kind != TextType.POINTTEXT) {
items.push(text.textPath);
}
}
@@ -198,13 +200,16 @@ function reset(items) {
var ANCHOR = PathPointSelection.ANCHORPOINT;
var NOSELECTION = PathPointSelection.NOSELECTION;
for (var i = 0; i < items.length; i++) {
- var points = items[i].parent.pathPoints;
+ var item = items[i];
+ var points = item.parent.pathPoints;
for (var j = 0; j < points.length; j++) {
- points[j].selected = NOSELECTION;
+ var point = points[j];
+ point.selected = NOSELECTION;
}
}
for (var i = 0; i < items.length; i++) {
- items[i].selected = ANCHOR;
+ var point = items[i];
+ point.selected = ANCHOR;
}
}
@@ -215,6 +220,16 @@ function round(value) {
}
+function getValue(text) {
+ var twoByteChar = /[!-~]/g;
+ var value = text.replace(twoByteChar, function(str) {
+ return String.fromCharCode(str.charCodeAt(0) - 0xFEE0);
+ });
+ if (isNaN(value) || !value) return 0;
+ return Number(value);
+}
+
+
function convertUnits(value, unit) {
try {
return Number(UnitValue(value).as(unit));
@@ -225,20 +240,80 @@ function convertUnits(value, unit) {
}
-function getUnits(ruler) {
- switch (ruler) {
- case RulerUnits.Millimeters: return 'mm';
- case RulerUnits.Centimeters: return 'cm';
- case RulerUnits.Inches: return 'in';
- case RulerUnits.Points: return 'pt';
- case RulerUnits.Pixels: return 'px';
- default: return 'pt';
+function getRulerUnits() {
+ var unit = getUnitSymbol();
+ if (!app.documents.length) return unit.pt;
+
+ var document = app.activeDocument;
+ var src = document.fullName;
+ var ruler = document.rulerUnits;
+ try {
+ switch (ruler) {
+ case RulerUnits.Pixels: return unit.px;
+ case RulerUnits.Points: return unit.pt;
+ case RulerUnits.Picas: return unit.pc;
+ case RulerUnits.Inches: return unit.inch;
+ case RulerUnits.Millimeters: return unit.mm;
+ case RulerUnits.Centimeters: return unit.cm;
+
+ case RulerUnits.Feet: return unit.ft;
+ case RulerUnits.Yards: return unit.yd;
+ case RulerUnits.Meters: return unit.meter;
+ }
+ }
+ catch (err) {
+ switch (xmpRulerUnits(src)) {
+ case 'Feet': return unit.ft;
+ case 'Yards': return unit.yd;
+ case 'Meters': return unit.meter;
+ }
}
+ return unit.pt;
+}
+
+
+function xmpRulerUnits(src) {
+ if (!ExternalObject.AdobeXMPScript) {
+ ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
+ }
+ var xmpFile = new XMPFile(src.fsName, XMPConst.FILE_UNKNOWN, XMPConst.OPEN_FOR_READ);
+ var xmpPackets = xmpFile.getXMP();
+ var xmp = new XMPMeta(xmpPackets.serialize());
+
+ var namespace = 'http://ns.adobe.com/xap/1.0/t/pg/';
+ var prop = 'xmpTPg:MaxPageSize';
+ var unit = prop + '/stDim:unit';
+
+ var ruler = xmp.getProperty(namespace, unit).value;
+ return ruler;
+}
+
+
+function getUnitSymbol() {
+ return {
+ px: 'px',
+ pt: 'pt',
+ pc: 'pc',
+ inch: 'in',
+ ft: 'ft',
+ yd: 'yd',
+ mm: 'mm',
+ cm: 'cm',
+ meter: 'm'
+ };
+}
+
+
+function isValidVersion() {
+ var cs4 = 14;
+ var aiVersion = parseInt(app.version);
+ if (aiVersion < cs4) return false;
+ return true;
}
function getDimension(points) {
- var units = getUnits(app.activeDocument.rulerUnits);
+ var units = getRulerUnits();
var deg = 180 / Math.PI;
var p1 = setPosition(points[0]);
var p2 = setPosition(points[1]);
@@ -267,15 +342,26 @@ function getDimension(points) {
}
-function getConfig(dialog) {
- var units = getUnits(app.activeDocument.rulerUnits);
+function preview(dialog, points) {
+ if (!dialog.preview.value) return;
+ reset(points);
+ var config = getConfiguration(dialog);
+ var p1 = points[0];
+ var p2 = points[1];
+ extendHandle(p1, p2, config.distance, config.angle);
+ app.redraw();
+}
+
+
+function getConfiguration(dialog) {
+ var units = getRulerUnits();
var distance = {
- left: Number(dialog.distance.left.text),
- right: Number(dialog.distance.right.text)
+ left: getValue(dialog.distance.left.text),
+ right: getValue(dialog.distance.right.text)
};
var angle = {
- left: Number(dialog.angle.left.text),
- right: Number(dialog.angle.right.text)
+ left: getValue(dialog.angle.left.text),
+ right: getValue(dialog.angle.right.text)
};
return {
distance: {
@@ -294,7 +380,7 @@ function showDialog(points, showHandles) {
$.localize = true;
var ui = localizeUI();
var dimension = getDimension(points);
- var units = getUnits(app.activeDocument.rulerUnits);
+ var units = getRulerUnits();
var dialog = new Window('dialog');
dialog.text = ui.title;
@@ -519,9 +605,10 @@ function showDialog(points, showHandles) {
group12.spacing = 10;
group12.margins = 0;
- // Work around the problem of being unable to undo the ESC key during localization.
+ // Work around the problem of not being able to undo with the esc key due to localization.
var button0 = group12.add('button', undefined, undefined, { name: 'button0' });
button0.text = 'Cancel';
+ button0.preferredSize.width = 20;
button0.hide();
var button1 = group12.add('button', undefined, undefined, { name: 'button1' });
@@ -532,6 +619,42 @@ function showDialog(points, showHandles) {
button2.text = ui.ok;
button2.preferredSize.width = 90;
+ edittext1.onChanging = function() {
+ preview(dialog, points);
+ }
+
+ edittext2.onChanging = function() {
+ preview(dialog, points);
+ }
+
+ edittext3.onChanging = function() {
+ preview(dialog, points);
+ }
+
+ edittext4.onChanging = function() {
+ preview(dialog, points);
+ }
+
+ edittext1.addEventListener('keydown', function(event) {
+ setIncreaseDecrease(event);
+ preview(dialog, points);
+ });
+
+ edittext2.addEventListener('keydown', function(event) {
+ setIncreaseDecrease(event);
+ preview(dialog, points);
+ });
+
+ edittext3.addEventListener('keydown', function(event) {
+ setIncreaseDecrease(event);
+ preview(dialog, points);
+ });
+
+ edittext4.addEventListener('keydown', function(event) {
+ setIncreaseDecrease(event);
+ preview(dialog, points);
+ });
+
statictext1.addEventListener('click', function() {
edittext1.active = false;
edittext1.active = true;
@@ -576,6 +699,23 @@ function showDialog(points, showHandles) {
}
+function setIncreaseDecrease(event) {
+ var value = getValue(event.target.text);
+ var keyboard = ScriptUI.environment.keyboardState;
+ var step = keyboard.shiftKey ? 5 : 1;
+ if (event.keyName == 'Up') {
+ value += step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+ if (event.keyName == 'Down') {
+ value -= step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+}
+
+
function localizeUI() {
return {
title: {
diff --git a/scripts/extendLine.js b/scripts/extendLine.js
index 01cd96d..9c2a105 100755
--- a/scripts/extendLine.js
+++ b/scripts/extendLine.js
@@ -2,14 +2,15 @@
extendLine
Description
- This script extends and shrinks a path object.
+ This script extends and shrinks path segments.
Usage
- 1. Select an anchor point with Direct Selection Tool, run this script from File > Scripts > Other Script...
+ 1. Select any anchor points with the Direct Selection Tool, run this script from File > Scripts > Other Script...
2. Enter a positive value to extend or a negative value to shrink.
Notes
Closed paths and curves are not supported.
+ Anchor points for type on a path are also supported.
The units of distance depend on the ruler units.
In rare cases, the script may not work if you continue to use it.
In this case, restart Illustrator and try again.
@@ -18,7 +19,7 @@
Illustrator CS4 or higher
Version
- 1.1.0
+ 1.2.0
Homepage
github.com/sky-chaser-high/adobe-illustrator-scripts
@@ -29,28 +30,31 @@
=============================================================================================================================================== */
(function() {
- if (app.documents.length > 0) main();
+ if (app.documents.length && isValidVersion()) main();
})();
function main() {
var items = app.activeDocument.selection;
var shapes = getPathItems(items);
+ var texts = getTextPathItems();
+ shapes = shapes.concat(texts);
+
var points = getSelectedPoints(shapes);
if (!points.length) return;
var dialog = showDialog(points);
dialog.ok.onClick = function() {
- if (dialog.preview.value) reset(points);
- var distance = Number(dialog.distance.text);
+ if (dialog.preview.value) return dialog.close();
+ var distance = getValue(dialog.distance.text);
extendLine(distance, points);
dialog.close();
}
dialog.preview.onClick = function() {
if (dialog.preview.value) {
- var distance = Number(dialog.distance.text);
+ var distance = getValue(dialog.distance.text);
extendLine(distance, points);
}
else {
@@ -59,63 +63,81 @@ function main() {
app.redraw();
}
+ dialog.distance.onChanging = function() {
+ if (dialog.preview.value) {
+ reset(points);
+ var distance = getValue(dialog.distance.text);
+ extendLine(distance, points);
+ app.redraw();
+ }
+ }
+
+ dialog.distance.addEventListener('keydown', function(event) {
+ var value = getValue(this.text);
+ var keyboard = ScriptUI.environment.keyboardState;
+ var step = keyboard.shiftKey ? 5 : 1;
+ var distance;
+ if (event.keyName == 'Up') {
+ distance = value + step;
+ this.text = distance;
+ event.preventDefault();
+ }
+ if (event.keyName == 'Down') {
+ distance = value - step;
+ this.text = distance;
+ event.preventDefault();
+ }
+ if (dialog.preview.value) {
+ reset(points);
+ extendLine(distance, points);
+ app.redraw();
+ }
+ });
+
dialog.show();
}
function extendLine(value, points) {
- var units = getUnits(app.activeDocument.rulerUnits);
+ var units = getRulerUnits();
var distance = convertUnits(value + units, 'pt');
for (var i = 0; i < points.length; i++) {
var point = setPoints(points[i]);
- if (!point) continue;
var position = getPosition(distance, point);
-
- points[i].anchor = [position.x, position.y];
- points[i].leftDirection = [position.x, position.y];
- points[i].rightDirection = [position.x, position.y];
+ var item = points[i].point1;
+ item.anchor = position;
+ item.leftDirection = position;
+ item.rightDirection = position;
}
}
-function getPosition(distance, point) {
- var rad = getAngle(point);
- var x = distance * Math.cos(rad);
- var y = distance * Math.sin(rad);
+function setPoints(item) {
return {
- x: point.x1 + x,
- y: point.y1 + y
+ x1: item.point1.anchor[0],
+ y1: item.point1.anchor[1],
+ x2: item.point2.anchor[0],
+ y2: item.point2.anchor[1]
};
}
-function getAngle(point) {
- var adjacent = point.x1 - point.x2;
- var opposite = point.y1 - point.y2;
- return Math.atan2(opposite, adjacent);
+function getPosition(distance, point) {
+ var rad = getAngle(point);
+ var x = distance * Math.cos(rad);
+ var y = distance * Math.sin(rad);
+ return [
+ point.x1 + x,
+ point.y1 + y
+ ];
}
-function setPoints(item) {
- var ANCHOR = PathPointSelection.ANCHORPOINT;
- var points = item.parent.pathPoints;
- for (var i = 0; i < points.length; i++) {
- var target = points[i];
- if (target.selected != ANCHOR) continue;
-
- var x1 = target.anchor[0];
- var y1 = target.anchor[1];
-
- var p = (i == 0) ? i + 1 : points.length - 2;
- if (p == i) return undefined;
-
- var point = points[p];
- var x2 = point.anchor[0];
- var y2 = point.anchor[1];
-
- return { x1: x1, y1: y1, x2: x2, y2: y2 };
- }
+function getAngle(point) {
+ var width = point.x1 - point.x2;
+ var height = point.y1 - point.y2;
+ return Math.atan2(height, width);
}
@@ -124,9 +146,19 @@ function getSelectedPoints(shapes) {
var selection = [];
for (var i = 0; i < shapes.length; i++) {
var points = shapes[i].pathPoints;
- for (var j = 0; j < points.length; j++) {
- var point = points[j];
- if (point.selected == ANCHOR) selection.push(point);
+ var start = 0;
+ var end = points.length - 1;
+
+ var p1 = points[start];
+ var p2 = points[start + 1];
+ if (p1.selected == ANCHOR) {
+ selection.push({ point1: p1, point2: p2 });
+ }
+
+ p1 = points[end];
+ p2 = points[end - 1];
+ if (p1.selected == ANCHOR) {
+ selection.push({ point1: p1, point2: p2 });
}
}
return selection;
@@ -148,17 +180,45 @@ function getPathItems(items) {
}
+function getTextPathItems() {
+ var items = [];
+ var texts = app.activeDocument.textFrames;
+ for (var i = 0; i < texts.length; i++) {
+ var text = texts[i];
+ if (text.selected && text.kind == TextType.PATHTEXT) {
+ items.push(text.textPath);
+ }
+ }
+ return items;
+}
+
+
function reset(items) {
app.undo();
var ANCHOR = PathPointSelection.ANCHORPOINT;
var NOSELECTION = PathPointSelection.NOSELECTION;
for (var i = 0; i < items.length; i++) {
- var points = items[i].parent.pathPoints;
+ var item = items[i].point1;
+ var points = item.parent.pathPoints;
for (var j = 0; j < points.length; j++) {
- points[j].selected = NOSELECTION;
+ var point = points[j];
+ point.selected = NOSELECTION;
}
- items[i].selected = ANCHOR;
}
+ for (var i = 0; i < items.length; i++) {
+ var point = items[i].point1;
+ point.selected = ANCHOR;
+ }
+}
+
+
+function getValue(text) {
+ var twoByteChar = /[!-~]/g;
+ var value = text.replace(twoByteChar, function(str) {
+ return String.fromCharCode(str.charCodeAt(0) - 0xFEE0);
+ });
+ if (isNaN(value) || !value) return 0;
+ return Number(value);
}
@@ -172,15 +232,75 @@ function convertUnits(value, unit) {
}
-function getUnits(ruler) {
- switch (ruler) {
- case RulerUnits.Millimeters: return 'mm';
- case RulerUnits.Centimeters: return 'cm';
- case RulerUnits.Inches: return 'in';
- case RulerUnits.Points: return 'pt';
- case RulerUnits.Pixels: return 'px';
- default: return 'pt';
+function getRulerUnits() {
+ var unit = getUnitSymbol();
+ if (!app.documents.length) return unit.pt;
+
+ var document = app.activeDocument;
+ var src = document.fullName;
+ var ruler = document.rulerUnits;
+ try {
+ switch (ruler) {
+ case RulerUnits.Pixels: return unit.px;
+ case RulerUnits.Points: return unit.pt;
+ case RulerUnits.Picas: return unit.pc;
+ case RulerUnits.Inches: return unit.inch;
+ case RulerUnits.Millimeters: return unit.mm;
+ case RulerUnits.Centimeters: return unit.cm;
+
+ case RulerUnits.Feet: return unit.ft;
+ case RulerUnits.Yards: return unit.yd;
+ case RulerUnits.Meters: return unit.meter;
+ }
}
+ catch (err) {
+ switch (xmpRulerUnits(src)) {
+ case 'Feet': return unit.ft;
+ case 'Yards': return unit.yd;
+ case 'Meters': return unit.meter;
+ }
+ }
+ return unit.pt;
+}
+
+
+function xmpRulerUnits(src) {
+ if (!ExternalObject.AdobeXMPScript) {
+ ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
+ }
+ var xmpFile = new XMPFile(src.fsName, XMPConst.FILE_UNKNOWN, XMPConst.OPEN_FOR_READ);
+ var xmpPackets = xmpFile.getXMP();
+ var xmp = new XMPMeta(xmpPackets.serialize());
+
+ var namespace = 'http://ns.adobe.com/xap/1.0/t/pg/';
+ var prop = 'xmpTPg:MaxPageSize';
+ var unit = prop + '/stDim:unit';
+
+ var ruler = xmp.getProperty(namespace, unit).value;
+ return ruler;
+}
+
+
+function getUnitSymbol() {
+ return {
+ px: 'px',
+ pt: 'pt',
+ pc: 'pc',
+ inch: 'in',
+ ft: 'ft',
+ yd: 'yd',
+ mm: 'mm',
+ cm: 'cm',
+ meter: 'm'
+ };
+}
+
+
+function isValidVersion() {
+ var cs4 = 14;
+ var aiVersion = parseInt(app.version);
+ if (aiVersion < cs4) return false;
+ return true;
}
@@ -217,17 +337,18 @@ function showDialog(points) {
var checkbox1 = group2.add('checkbox', undefined, undefined, { name: 'checkbox1' });
checkbox1.text = ui.preview;
- // Work around the problem of being unable to undo the ESC key during localization.
- var button0 = group2.add('button', undefined, undefined, { name: 'button0' });
- button0.text = 'Cancel';
- button0.hide();
-
var group3 = dialog.add('group', undefined, { name: 'group3' });
group3.orientation = 'row';
group3.alignChildren = ['right', 'center'];
group3.spacing = 10;
group3.margins = 0;
+ // Work around the problem of not being able to undo with the esc key due to localization.
+ var button0 = group3.add('button', undefined, undefined, { name: 'button0' });
+ button0.text = 'Cancel';
+ button0.preferredSize.width = 20;
+ button0.hide();
+
var button1 = group3.add('button', undefined, undefined, { name: 'button1' });
button1.text = ui.cancel;
button1.preferredSize.width = 90;
diff --git a/scripts/rearrangeObjects.js b/scripts/rearrangeObjects.js
index 9071273..9229037 100755
--- a/scripts/rearrangeObjects.js
+++ b/scripts/rearrangeObjects.js
@@ -17,8 +17,8 @@
Notes
The object in the top-left is the basis for rearranging.
- The units of the Spacing and the Alignment Position Tolerance depend on the ruler units.
Compound paths, texts, linked files, and embedded link files are also supported.
+ The units of the Spacing and the Alignment Position Tolerance depend on the ruler units.
In rare cases, the script may not work if you continue to use it.
In this case, restart Illustrator and try again.
@@ -26,7 +26,7 @@
Illustrator 2021 or higher
Version
- 1.0.0
+ 1.1.0
Homepage
github.com/sky-chaser-high/adobe-illustrator-scripts
@@ -49,44 +49,68 @@ function main() {
var layout = 'Rows';
var order = 'RowLR';
- var ruler = app.activeDocument.rulerUnits;
- var units = getUnits(ruler);
- var dialog = showDialog(shapes, units);
+ var dialog = showDialog();
+
+ dialog.ok.onClick = function() {
+ if (dialog.preview.value) return dialog.close();
+ var config = getConfiguration(dialog);
+ rearrange(shapes, layout, order, config);
+ app.close();
+ }
+
+ dialog.preview.onClick = function() {
+ if (dialog.preview.value) {
+ var config = getConfiguration(dialog);
+ rearrange(shapes, layout, order, config);
+ }
+ else {
+ app.undo();
+ }
+ app.redraw();
+ }
dialog.align.rows.addEventListener('click', function() {
layout = 'Rows';
+ preview(dialog, shapes, layout, order);
});
dialog.align.columns.addEventListener('click', function() {
layout = 'Columns';
+ preview(dialog, shapes, layout, order);
});
dialog.align.row.addEventListener('click', function() {
layout = 'Row';
+ preview(dialog, shapes, layout, order);
});
dialog.align.column.addEventListener('click', function() {
layout = 'Column';
+ preview(dialog, shapes, layout, order);
});
dialog.order.rowLR.addEventListener('click', function() {
order = 'RowLR';
if (dialog.reverse.value) order = 'RowLR_Reverse';
+ preview(dialog, shapes, layout, order);
});
dialog.order.columnLR.addEventListener('click', function() {
order = 'ColumnLR';
if (dialog.reverse.value) order = 'ColumnLR_Reverse';
+ preview(dialog, shapes, layout, order);
});
dialog.order.rowRL.addEventListener('click', function() {
order = 'RowRL';
if (dialog.reverse.value) order = 'RowRL_Reverse';
+ preview(dialog, shapes, layout, order);
});
dialog.order.columnRL.addEventListener('click', function() {
order = 'ColumnRL';
if (dialog.reverse.value) order = 'ColumnRL_Reverse';
+ preview(dialog, shapes, layout, order);
});
dialog.reverse.onClick = function() {
@@ -103,24 +127,38 @@ function main() {
rowRL: dialog.order.rowRL,
columnRL: dialog.order.columnRL
}, order, dialog.reverse.value);
+ preview(dialog, shapes, layout, order);
}
- dialog.ok.onClick = function() {
- if (dialog.preview.value) app.undo();
- var config = getConfiguration(dialog);
- rearrange(shapes, layout, order, config);
- app.close();
+ dialog.count.addEventListener('keydown', function(event) {
+ setCountValue(event);
+ preview(dialog, shapes, layout, order);
+ });
+
+ dialog.count.onChanging = function() {
+ preview(dialog, shapes, layout, order);
}
- dialog.preview.onClick = function() {
- if (dialog.preview.value) {
- var config = getConfiguration(dialog);
- rearrange(shapes, layout, order, config);
- }
- else {
- app.undo();
- }
- app.redraw();
+ dialog.margin.addEventListener('keydown', function(event) {
+ setMarginValue(event);
+ preview(dialog, shapes, layout, order);
+ });
+
+ dialog.margin.onChanging = function() {
+ preview(dialog, shapes, layout, order);
+ }
+
+ dialog.stroke.onClick = function() {
+ preview(dialog, shapes, layout, order);
+ }
+
+ dialog.tolerance.addEventListener('keydown', function(event) {
+ setToleranceValue(event);
+ preview(dialog, shapes, layout, order);
+ });
+
+ dialog.tolerance.onChanging = function() {
+ preview(dialog, shapes, layout, order);
}
dialog.show();
@@ -137,7 +175,7 @@ function getConfiguration(dialog) {
var units = dialog.units;
return {
- count: count,
+ count: parseInt(count),
margin: {
x: convertUnits(x + units, 'pt'),
y: convertUnits(y + units, 'pt')
@@ -148,15 +186,19 @@ function getConfiguration(dialog) {
}
-function getValue(item) {
- if (isNaN(item)) return 0;
- return Number(item);
+function preview(dialog, shapes, layout, order) {
+ if (!dialog.preview.value) return;
+ app.undo();
+ app.redraw();
+ var config = getConfiguration(dialog);
+ rearrange(shapes, layout, order, config);
+ app.redraw();
}
function rearrange(items, layout, order, config) {
var position = getStartPosition(items, config.tolerance, config.stroke);
- var shapes = getSortedItems(items, order, config.tolerance);
+ var shapes = getSortedItems(items, order, config.tolerance, config.stroke);
setStartPosition(shapes[0], position, config.stroke);
switch (layout) {
@@ -353,7 +395,7 @@ function getPosition(item, hasStroke) {
function getStartPosition(items, tolerance, hasStroke) {
- var rows = sortRow(items, tolerance);
+ var rows = sortRow(items, tolerance, hasStroke);
var item = rows[0];
return getPosition(item, hasStroke);
}
@@ -424,88 +466,124 @@ function getStrokeWidth(item) {
}
-function sortRow(items, tolerance) {
+function sortRow(items, tolerance, hasStroke) {
return items.sort(function(a, b) {
- var item = { a: a, b: b };
- if (isClipped(item.a)) item.a = item.a.pageItems[0];
- if (isClipped(item.b)) item.b = item.b.pageItems[0];
- var distance = Math.abs(item.b.top - item.a.top);
+ var itemA = a;
+ var itemB = b;
+ if (isClipped(itemA)) itemA = itemA.pageItems[0];
+ if (isClipped(itemB)) itemB = itemB.pageItems[0];
+
+ var boundsA = hasStroke ? itemA.visibleBounds : itemA.geometricBounds;
+ var boundsB = hasStroke ? itemB.visibleBounds : itemB.geometricBounds;
+ var topA = boundsA[1];
+ var topB = boundsB[1];
+ var leftA = boundsA[0];
+ var leftB = boundsB[0];
+
+ var distance = Math.abs(topB - topA);
if (distance <= tolerance) {
- return item.a.left - item.b.left;
+ return leftA - leftB;
}
- return item.b.top - item.a.top;
+ return topB - topA;
});
}
-function sortRowRL(items, tolerance) {
+function sortRowRL(items, tolerance, hasStroke) {
return items.sort(function(a, b) {
- var item = { a: a, b: b };
- if (isClipped(item.a)) item.a = item.a.pageItems[0];
- if (isClipped(item.b)) item.b = item.b.pageItems[0];
- var distance = Math.abs(item.b.top - item.a.top);
+ var itemA = a;
+ var itemB = b;
+ if (isClipped(itemA)) itemA = itemA.pageItems[0];
+ if (isClipped(itemB)) itemB = itemB.pageItems[0];
+
+ var boundsA = hasStroke ? itemA.visibleBounds : itemA.geometricBounds;
+ var boundsB = hasStroke ? itemB.visibleBounds : itemB.geometricBounds;
+ var topA = boundsA[1];
+ var topB = boundsB[1];
+ var leftA = boundsA[0];
+ var leftB = boundsB[0];
+
+ var distance = Math.abs(topB - topA);
if (distance <= tolerance) {
- return item.b.left - item.a.left;
+ return leftB - leftA;
}
- return item.b.top - item.a.top;
+ return topB - topA;
});
}
-function sortColumn(items, tolerance) {
+function sortColumn(items, tolerance, hasStroke) {
return items.sort(function(a, b) {
- var item = { a: a, b: b };
- if (isClipped(item.a)) item.a = item.a.pageItems[0];
- if (isClipped(item.b)) item.b = item.b.pageItems[0];
- var distance = Math.abs(item.a.left - item.b.left);
+ var itemA = a;
+ var itemB = b;
+ if (isClipped(itemA)) itemA = itemA.pageItems[0];
+ if (isClipped(itemB)) itemB = itemB.pageItems[0];
+
+ var boundsA = hasStroke ? itemA.visibleBounds : itemA.geometricBounds;
+ var boundsB = hasStroke ? itemB.visibleBounds : itemB.geometricBounds;
+ var topA = boundsA[1];
+ var topB = boundsB[1];
+ var leftA = boundsA[0];
+ var leftB = boundsB[0];
+
+ var distance = Math.abs(leftA - leftB);
if (distance <= tolerance) {
- return item.b.top - item.a.top;
+ return topB - topA;
}
- return item.a.left - item.b.left;
+ return leftA - leftB;
});
}
-function sortColumnRL(items, tolerance) {
+function sortColumnRL(items, tolerance, hasStroke) {
return items.sort(function(a, b) {
- var item = { a: a, b: b };
- if (isClipped(item.a)) item.a = item.a.pageItems[0];
- if (isClipped(item.b)) item.b = item.b.pageItems[0];
- var distance = Math.abs(item.b.left - item.a.left);
+ var itemA = a;
+ var itemB = b;
+ if (isClipped(itemA)) itemA = itemA.pageItems[0];
+ if (isClipped(itemB)) itemB = itemB.pageItems[0];
+
+ var boundsA = hasStroke ? itemA.visibleBounds : itemA.geometricBounds;
+ var boundsB = hasStroke ? itemB.visibleBounds : itemB.geometricBounds;
+ var topA = boundsA[1];
+ var topB = boundsB[1];
+ var leftA = boundsA[0];
+ var leftB = boundsB[0];
+
+ var distance = Math.abs(leftB - leftA);
if (distance <= tolerance) {
- return item.b.top - item.a.top;
+ return topB - topA;
}
- return item.b.left - item.a.left;
+ return leftB - leftA;
});
}
-function getSortedItems(items, order, tolerance) {
+function getSortedItems(items, order, tolerance, hasStroke) {
var rows, columns;
switch (order) {
case 'RowLR':
- rows = sortRow(items, tolerance);
+ rows = sortRow(items, tolerance, hasStroke);
return rows;
case 'ColumnLR':
- columns = sortColumn(items, tolerance);
+ columns = sortColumn(items, tolerance, hasStroke);
return columns;
case 'RowRL':
- rows = sortRowRL(items, tolerance);
+ rows = sortRowRL(items, tolerance, hasStroke);
return rows;
case 'ColumnRL':
- columns = sortColumnRL(items, tolerance);
+ columns = sortColumnRL(items, tolerance, hasStroke);
return columns;
case 'RowLR_Reverse':
- rows = sortRow(items, tolerance);
+ rows = sortRow(items, tolerance, hasStroke);
return rows.reverse();
case 'ColumnLR_Reverse':
- columns = sortColumn(items, tolerance);
+ columns = sortColumn(items, tolerance, hasStroke);
return columns.reverse();
case 'RowRL_Reverse':
- rows = sortRowRL(items, tolerance);
+ rows = sortRowRL(items, tolerance, hasStroke);
return rows.reverse();
case 'ColumnRL_Reverse':
- columns = sortColumnRL(items, tolerance);
+ columns = sortColumnRL(items, tolerance, hasStroke);
return columns.reverse();
}
}
@@ -521,6 +599,16 @@ function getPageItems(items) {
}
+function getValue(text) {
+ var twoByteChar = /[!-~]/g;
+ var value = text.replace(twoByteChar, function(str) {
+ return String.fromCharCode(str.charCodeAt(0) - 0xFEE0);
+ });
+ if (isNaN(value) || !value) return 0;
+ return Number(value);
+}
+
+
function convertUnits(value, unit) {
try {
return Number(UnitValue(value).as(unit));
@@ -531,25 +619,81 @@ function convertUnits(value, unit) {
}
-function getUnits(unit) {
- switch (unit) {
- case RulerUnits.Millimeters: return 'mm';
- case RulerUnits.Centimeters: return 'cm';
- case RulerUnits.Inches: return 'inch';
- case RulerUnits.Points: return 'pt';
- case RulerUnits.Pixels: return 'px';
- default: return 'pt';
+function getRulerUnits() {
+ var unit = getUnitSymbol();
+ if (!app.documents.length) return unit.pt;
+
+ var document = app.activeDocument;
+ var src = document.fullName;
+ var ruler = document.rulerUnits;
+ try {
+ switch (ruler) {
+ case RulerUnits.Pixels: return unit.px;
+ case RulerUnits.Points: return unit.pt;
+ case RulerUnits.Picas: return unit.pc;
+ case RulerUnits.Inches: return unit.inch;
+ case RulerUnits.Millimeters: return unit.mm;
+ case RulerUnits.Centimeters: return unit.cm;
+
+ case RulerUnits.Feet: return unit.ft;
+ case RulerUnits.Yards: return unit.yd;
+ case RulerUnits.Meters: return unit.meter;
+ }
}
+ catch (err) {
+ switch (xmpRulerUnits(src)) {
+ case 'Feet': return unit.ft;
+ case 'Yards': return unit.yd;
+ case 'Meters': return unit.meter;
+ }
+ }
+ return unit.pt;
+}
+
+
+function xmpRulerUnits(src) {
+ if (!ExternalObject.AdobeXMPScript) {
+ ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
+ }
+ var xmpFile = new XMPFile(src.fsName, XMPConst.FILE_UNKNOWN, XMPConst.OPEN_FOR_READ);
+ var xmpPackets = xmpFile.getXMP();
+ var xmp = new XMPMeta(xmpPackets.serialize());
+
+ var namespace = 'http://ns.adobe.com/xap/1.0/t/pg/';
+ var prop = 'xmpTPg:MaxPageSize';
+ var unit = prop + '/stDim:unit';
+
+ var ruler = xmp.getProperty(namespace, unit).value;
+ return ruler;
+}
+
+
+function getUnitSymbol() {
+ return {
+ px: 'px',
+ pt: 'pt',
+ pc: 'pc',
+ inch: 'in',
+ ft: 'ft',
+ yd: 'yd',
+ mm: 'mm',
+ cm: 'cm',
+ meter: 'm'
+ };
}
function getTolerance(unit) {
switch (unit) {
+ case 'px': return 30;
+ case 'pt': return 30;
+ case 'pc': return 1;
+ case 'in': return 0.5;
+ case 'ft': return 0.03;
+ case 'yd': return 0.01;
case 'mm': return 10;
case 'cm': return 1;
- case 'inch': return 0.5;
- case 'pt': return 30;
- case 'px': return 30;
+ case 'm': return 0.01;
}
}
@@ -597,10 +741,12 @@ function changeOrderIcon(dialog, order, isReverse) {
}
-function showDialog(items, units) {
+function showDialog() {
$.localize = true;
var ui = localizeUI();
var icon = getUIIcon();
+
+ var units = getRulerUnits();
var tolerance = getTolerance(units);
var state = {
layout: {
@@ -765,6 +911,12 @@ function showDialog(items, units) {
group11.spacing = 10;
group11.margins = 0;
+ // Work around the problem of not being able to undo with the esc key due to localization.
+ var button0 = group11.add('button', undefined, undefined, { name: 'button0' });
+ button0.text = 'Cancel';
+ button0.preferredSize.width = 20;
+ button0.hide();
+
var button1 = group11.add('button', undefined, undefined, { name: 'button1' });
button1.text = ui.cancel;
button1.preferredSize.width = 90;
@@ -1170,64 +1322,6 @@ function showDialog(items, units) {
});
- edittext1.addEventListener('keydown', function(event) {
- var value = Number(edittext1.text);
- if (isNaN(value)) value = 1;
- var keyboard = ScriptUI.environment.keyboardState;
- var step = keyboard.shiftKey ? 5 : 1;
- var count;
- if (event.keyName == 'Up') {
- count = value + step;
- if (count > items.length) count = items.length;
- edittext1.text = count;
- event.preventDefault();
- }
- if (event.keyName == 'Down') {
- count = value - step;
- if (count < 1) count = 1;
- edittext1.text = count;
- event.preventDefault();
- }
- });
-
- edittext2.addEventListener('keydown', function(event) {
- var value = Number(edittext2.text);
- if (isNaN(value)) value = 0;
- var keyboard = ScriptUI.environment.keyboardState;
- var step = keyboard.shiftKey ? 5 : 1;
- var margin;
- if (event.keyName == 'Up') {
- margin = value + step;
- edittext2.text = margin;
- event.preventDefault();
- }
- if (event.keyName == 'Down') {
- margin = value - step;
- if (margin < 0) margin = 0;
- edittext2.text = margin;
- event.preventDefault();
- }
- });
-
- edittext3.addEventListener('keydown', function(event) {
- var value = Number(edittext3.text);
- if (isNaN(value)) value = 0;
- var keyboard = ScriptUI.environment.keyboardState;
- var step = keyboard.shiftKey ? 5 : 1;
- var tolerance;
- if (event.keyName == 'Up') {
- tolerance = value + step;
- edittext3.text = tolerance;
- event.preventDefault();
- }
- if (event.keyName == 'Down') {
- tolerance = value - step;
- if (tolerance < 0) tolerance = 0;
- edittext3.text = tolerance;
- event.preventDefault();
- }
- });
-
statictext1.addEventListener('click', function() {
edittext1.active = false;
edittext1.active = true;
@@ -1243,14 +1337,15 @@ function showDialog(items, units) {
edittext3.active = true;
});
- button1.onClick = function() {
- if (checkbox3.value) {
- app.undo();
- app.redraw();
- }
+ button0.onClick = function() {
+ if (checkbox3.value) app.undo();
dialog.close();
}
+ button1.onClick = function() {
+ button0.notify('onClick');
+ }
+
dialog.align = {
rows: image1,
columns: image2,
@@ -1275,6 +1370,59 @@ function showDialog(items, units) {
}
+function setCountValue(event) {
+ var value = getValue(event.target.text);
+ var keyboard = ScriptUI.environment.keyboardState;
+ var step = keyboard.shiftKey ? 5 : 1;
+ if (event.keyName == 'Up') {
+ value += step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+ if (event.keyName == 'Down') {
+ value -= step;
+ if (value < 1) value = 1;
+ event.target.text = value;
+ event.preventDefault();
+ }
+}
+
+
+function setMarginValue(event) {
+ var value = getValue(event.target.text);
+ var keyboard = ScriptUI.environment.keyboardState;
+ var step = keyboard.shiftKey ? 5 : 1;
+ if (event.keyName == 'Up') {
+ value += step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+ if (event.keyName == 'Down') {
+ value -= step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+}
+
+
+function setToleranceValue(event) {
+ var value = getValue(event.target.text);
+ var keyboard = ScriptUI.environment.keyboardState;
+ var step = keyboard.shiftKey ? 5 : 1;
+ if (event.keyName == 'Up') {
+ value += step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+ if (event.keyName == 'Down') {
+ value -= step;
+ if (value < 0) value = 0;
+ event.target.text = value;
+ event.preventDefault();
+ }
+}
+
+
function getUIIcon() {
var lightest = {
normal: {
diff --git a/scripts/showDimensions.js b/scripts/showDimensions.js
index 10e91a3..f22bd9d 100755
--- a/scripts/showDimensions.js
+++ b/scripts/showDimensions.js
@@ -5,21 +5,24 @@
This script shows the dimension of the anchor point between two points of the path objects.
Usage
- Select the path object, run this script from File > Scripts > Other Script...
+ Select any path objects, run this script from File > Scripts > Other Script...
+ If you select anchor points with the Direct Selection Tool,
+ dimensions are displayed only at the selected. In this case, select at least two anchor points.
Notes
+ The Dimension Tool has been implemented in the Toolbar since version 2024.
Supports curves.
Group and color dimensions by path object.
- The dimension units depend on the ruler units.
In complex shapes, dimensions may be displayed overlapping each other.
+ The dimension units depend on the ruler units.
In rare cases, the script may not work if you continue to use it.
In this case, restart Illustrator and try again.
Requirements
- Illustrator CS6 or higher
+ Illustrator CS4 or higher
Version
- 2.0.0
+ 2.1.0
Homepage
github.com/sky-chaser-high/adobe-illustrator-scripts
@@ -30,7 +33,7 @@
=============================================================================================================================================== */
(function() {
- if (app.documents.length > 0) main();
+ if (app.documents.length && isValidVersion()) main();
})();
@@ -39,34 +42,41 @@ function main() {
var shapes = getPathItems(items);
if (!shapes.length) return;
- var layer = getLayer('Dimensions');
var colors = setColors();
for (var i = 0; i < shapes.length; i++) {
- measure(shapes[i], layer, colors[i % colors.length]);
+ var shape = shapes[i];
+ if (!hasSelectedAnchorPoints(shape)) continue;
+ var color = colors[i % colors.length];
+ measure(shape, color);
}
}
-function measure(item, layer, color) {
+function measure(item, color) {
if (item.polarity == PolarityValues.POSITIVE) {
- app.executeMenuCommand('Reverse Path Direction');
+ item.polarity = PolarityValues.NEGATIVE;
}
-
+ var layer = getLayer('Dimensions');
var group = layer.groupItems.add();
+
var points = item.pathPoints;
var count = points.length;
if (!item.closed) count--;
- for (var i = 0; i < count; i++) {
- var last = (i == points.length - 1) ? true : false;
+ var start = 0;
+ var end = points.length - 1;
+
+ for (var i = start; i < count; i++) {
+ if (!isSelected(item, i)) continue;
+
var p1 = setPoint(points[i]);
- var p2 = (last) ? setPoint(points[0]) : setPoint(points[i + 1]);
+ var p2 = (i < end) ? setPoint(points[i + 1]) : setPoint(points[start]);
var position = getPosition(p1.anchor, p2.anchor);
var distance = getDistance(p1.anchor, p2.anchor);
- if (hasCurve(p1, p2)) {
+ if (isCurve(p1, p2)) {
var bezier = setBezier(p1, p2);
distance = getCurveLength(bezier);
var t = completion(0.5, bezier);
@@ -79,6 +89,56 @@ function measure(item, layer, color) {
}
+function showDimension(distance, group, position, color) {
+ var units = getRulerUnits();
+ var value = convertUnits(distance + 'pt', units);
+ var contents = round(value) + ' ' + units;
+
+ var text = group.textFrames.pointText([position.x, position.y]);
+ text.contents = contents;
+
+ var paragraph = text.textRange.paragraphAttributes;
+ paragraph.justification = Justification.CENTER;
+
+ var font = getFont('SourceHanSansJP-Normal');
+ var fontsize = 7;
+ var scale = 100;
+
+ var attributes = text.textRange.characterAttributes;
+ if (font) attributes.textFont = font;
+ attributes.size = fontsize;
+ attributes.horizontalScale = scale;
+ attributes.verticalScale = scale;
+ attributes.fillColor = color;
+ attributes.strokeColor = new NoColor();
+
+ movePosition(text, distance, position.angle);
+}
+
+
+function movePosition(text, distance, angle) {
+ if (text.width > distance) {
+ var ratio = distance / text.width * 100;
+ var attributes = text.textRange.characterAttributes;
+ attributes.horizontalScale = (ratio > 50) ? ratio : 50;
+ }
+
+ var deg = angle * 180 / Math.PI;
+ text.rotate(deg);
+
+ var margin = convertUnits(1 + 'mm', 'pt');
+ var rad = angle + Math.PI / 2;
+ text.top += margin * Math.sin(rad);
+ text.left += margin * Math.cos(rad);
+}
+
+
+function round(value) {
+ var digits = 1000;
+ return Math.round(value * digits) / digits;
+}
+
+
function setPoint(item) {
var anchor = item.anchor;
var left = item.leftDirection;
@@ -107,17 +167,17 @@ function getPosition(p1, p2) {
function getAngle(p1, p2) {
- var adjacent = p2.x - p1.x;
- var opposite = p2.y - p1.y;
- return Math.atan2(opposite, adjacent);
+ var width = p2.x - p1.x;
+ var height = p2.y - p1.y;
+ return Math.atan2(height, width);
}
function getDistance(p1, p2) {
- var adjacent = p2.x - p1.x;
- var opposite = p2.y - p1.y;
- var hypotenuse = Math.sqrt(Math.pow(adjacent, 2) + Math.pow(opposite, 2));
- return hypotenuse;
+ var width = p2.x - p1.x;
+ var height = p2.y - p1.y;
+ var sq = 2;
+ return Math.sqrt(Math.pow(width, sq) + Math.pow(height, sq));
}
@@ -136,9 +196,10 @@ function getCurveLength(bezier) {
}
for (var i = 0; i < points.length - 1; i++) {
- length += getDistance(points[i], points[i + 1]);
+ var p1 = points[i];
+ var p2 = points[i + 1];
+ length += getDistance(p1, p2);
}
-
return length;
}
@@ -204,46 +265,42 @@ function mult(a, t) {
}
-function showDimension(distance, group, position, color) {
- var units = getUnits(app.activeDocument.rulerUnits);
- var contents = round(convertUnits(distance + 'pt', units)) + ' ' + units;
-
- var text = group.textFrames.pointText([position.x, position.y]);
- text.contents = contents;
- text.textRange.paragraphAttributes.justification = Justification.CENTER;
+function hasHandle(anchor, handle) {
+ return anchor.x != handle.x || anchor.y != handle.y;
+}
- var fontsize = 7;
- var attributes = text.textRange.characterAttributes;
- attributes.textFont = getFont('SourceHanSansJP-Normal');
- attributes.size = fontsize;
- attributes.horizontalScale = 100;
- attributes.verticalScale = 100;
- attributes.fillColor = color;
- attributes.strokeColor = new NoColor();
- movePosition(text, distance, position.angle);
+function isCurve(p1, p2) {
+ var left = hasHandle(p2.anchor, p2.handle.left);
+ var right = hasHandle(p1.anchor, p1.handle.right);
+ return left || right;
}
-function movePosition(text, distance, angle) {
- if (text.width > distance) {
- var ratio = distance / text.width * 100;
- text.textRange.characterAttributes.horizontalScale = (ratio > 50) ? ratio :50;
+function hasSelectedAnchorPoints(item) {
+ var count = 0;
+ var points = item.pathPoints;
+ for (var i = 0; i < points.length; i++) {
+ if (isSelected(item, i)) count++;
}
+ return count > 0;
+}
- var deg = angle * 180 / Math.PI;
- text.rotate(deg);
- var margin = convertUnits(1 + 'mm', 'pt');
- var rad = angle + Math.PI / 2;
- text.top += margin * Math.sin(rad);
- text.left += margin * Math.cos(rad);
-}
+function isSelected(item, index) {
+ var ANCHOR = PathPointSelection.ANCHORPOINT;
+ var points = item.pathPoints;
+ var p1 = points[index];
+ if (p1.selected != ANCHOR) return false;
-function round(value) {
- var digits = 1000;
- return Math.round(value * digits) / digits;
+ var last = points.length - 1;
+ if (index == last && !item.closed) return false;
+
+ var next = (index < last) ? index + 1 : 0;
+ var p2 = points[next];
+ if (p2.selected != ANCHOR) return false;
+ return true;
}
@@ -321,14 +378,12 @@ function setRGBColor(r, g, b) {
}
-function getUnits(ruler) {
- switch (ruler) {
- case RulerUnits.Millimeters: return 'mm';
- case RulerUnits.Centimeters: return 'cm';
- case RulerUnits.Inches: return 'in';
- case RulerUnits.Points: return 'pt';
- case RulerUnits.Pixels: return 'px';
- default: return 'pt';
+function getFont(name) {
+ try {
+ return app.textFonts[name];
+ }
+ catch (err) {
+ return;
}
}
@@ -343,29 +398,67 @@ function convertUnits(value, unit) {
}
-function getFont(name) {
+function getRulerUnits() {
+ var unit = getUnitSymbol();
+ if (!app.documents.length) return unit.pt;
+
+ var document = app.activeDocument;
+ var src = document.fullName;
+ var ruler = document.rulerUnits;
try {
- return app.textFonts[name];
+ switch (ruler) {
+ case RulerUnits.Pixels: return unit.px;
+ case RulerUnits.Points: return unit.pt;
+ case RulerUnits.Picas: return unit.pc;
+ case RulerUnits.Inches: return unit.inch;
+ case RulerUnits.Millimeters: return unit.mm;
+ case RulerUnits.Centimeters: return unit.cm;
+
+ case RulerUnits.Feet: return unit.ft;
+ case RulerUnits.Yards: return unit.yd;
+ case RulerUnits.Meters: return unit.meter;
+ }
}
catch (err) {
- return app.textFonts[0];
+ switch (xmpRulerUnits(src)) {
+ case 'Feet': return unit.ft;
+ case 'Yards': return unit.yd;
+ case 'Meters': return unit.meter;
+ }
}
+ return unit.pt;
}
-function hasCurve(p1, p2) {
- var handle = { left: false, right: false };
- handle.left = hasHandle(p2.anchor, p2.handle.left);
- handle.right = hasHandle(p1.anchor, p1.handle.right);
+function xmpRulerUnits(src) {
+ if (!ExternalObject.AdobeXMPScript) {
+ ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
+ }
+ var xmpFile = new XMPFile(src.fsName, XMPConst.FILE_UNKNOWN, XMPConst.OPEN_FOR_READ);
+ var xmpPackets = xmpFile.getXMP();
+ var xmp = new XMPMeta(xmpPackets.serialize());
+
+ var namespace = 'http://ns.adobe.com/xap/1.0/t/pg/';
+ var prop = 'xmpTPg:MaxPageSize';
+ var unit = prop + '/stDim:unit';
- if (handle.left || handle.right) return true;
- return false;
+ var ruler = xmp.getProperty(namespace, unit).value;
+ return ruler;
}
-function hasHandle(anchor, handle) {
- if (anchor.x == handle.x && anchor.y == handle.y) return false;
- return true;
+function getUnitSymbol() {
+ return {
+ px: 'px',
+ pt: 'pt',
+ pc: 'pc',
+ inch: 'in',
+ ft: 'ft',
+ yd: 'yd',
+ mm: 'mm',
+ cm: 'cm',
+ meter: 'm'
+ };
}
@@ -385,3 +478,11 @@ function getPathItems(items) {
}
return shapes;
}
+
+
+function isValidVersion() {
+ var cs6 = 16;
+ var aiVersion = parseInt(app.version);
+ if (aiVersion < cs6) return false;
+ return true;
+}
diff --git a/scripts/stepAndRepeat.js b/scripts/stepAndRepeat.js
index 5f4b358..bf8d16d 100755
--- a/scripts/stepAndRepeat.js
+++ b/scripts/stepAndRepeat.js
@@ -2,7 +2,7 @@
stepAndRepeat
Description
- This script is equivalent to InDesign's "Step and Repeat".
+ This script repeatedly duplicates selected objects. It is equivalent to InDesign's Edit > Step and Repeat.
Usage
1. Select any objects, run this script from File > Scripts > Other Script...
@@ -19,7 +19,7 @@
Illustrator CS4 or higher
Version
- 2.0.1
+ 2.1.0
Homepage
github.com/sky-chaser-high/adobe-illustrator-scripts
@@ -30,26 +30,32 @@
=============================================================================================================================================== */
(function() {
- if (app.documents.length > 0 && app.activeDocument.selection.length > 0) main();
+ if (app.documents.length && isValidVersion()) main();
})();
function main() {
- var dialog = showDialog();
+ var items = app.activeDocument.selection;
+ if (!items.length) return;
+
+ var dialog = showDialog(items);
dialog.ok.onClick = function() {
- if (!dialog.preview.value) {
- run(dialog);
- }
+ if (dialog.preview.value) return dialog.close();
+ var config = getConfiguration(dialog);
+ if (!validate(config)) return;
+ stepAndRepeat(config);
dialog.close();
}
dialog.preview.onClick = function() {
if (dialog.preview.value) {
- run(dialog);
+ var config = getConfiguration(dialog);
+ if (!validate(config)) return;
+ stepAndRepeat(config);
}
else {
- app.undo();
+ restore(items);
}
app.redraw();
}
@@ -58,45 +64,70 @@ function main() {
}
-function run(dialog) {
- var config = getConfig(dialog);
+function getConfiguration(dialog) {
+ var ruler = getRulerUnits();
+ var rows = getValue(dialog.rows.text);
+ var columns = getValue(dialog.columns.text);
+ var vertical = getValue(dialog.vertical.text);
+ var horizontal = getValue(dialog.horizontal.text);
+ return {
+ mode: {
+ repeat: dialog.grid.value ? false : true,
+ grid: dialog.grid.value ? true : false
+ },
+ rows: parseInt(rows),
+ columns: parseInt(columns),
+ vertical: convertUnits(vertical + ruler, 'pt'),
+ horizontal: convertUnits(horizontal + ruler, 'pt')
+ };
+}
+
+
+function preview(dialog, items) {
+ if (!dialog.preview.value) return;
+ restore(items);
+ var config = getConfiguration(dialog);
if (!validate(config)) return;
stepAndRepeat(config);
+ app.redraw();
}
-function preview(dialog) {
- if (dialog.preview.value) {
- app.undo();
- run(dialog);
- app.redraw();
+function restore(items) {
+ var current = app.activeDocument.selection;
+ if (items.length == current.length) return;
+ app.undo();
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ item.selected = true;
}
+ app.redraw();
}
function stepAndRepeat(config) {
var items = app.activeDocument.selection;
for (var i = 0; i < items.length; i++) {
- if (config.mode.repeat) repeat(items[i], config);
- if (config.mode.grid) grid(items[i], config);
+ var item = items[i];
+ if (config.mode.repeat) repeat(item, config);
+ if (config.mode.grid) grid(item, config);
}
- app.activeDocument.selection = null;
}
function repeat(item, config) {
+ var x = config.horizontal;
+ var y = config.vertical * -1;
for (var i = 0; i < config.rows; i++) {
item.duplicate();
- item.translate(config.horizontal, config.vertical * -1);
+ item.translate(x, y);
}
}
function grid(item, config) {
- var base = {
- top: item.top,
- left: item.left,
- };
+ var top = item.top;
+ var left = item.left;
for (var i = 0; i < config.rows; i++) {
for (var j = 0; j < config.columns - 1; j++) {
item.duplicate();
@@ -104,58 +135,102 @@ function grid(item, config) {
}
if (i < config.rows - 1) {
item.duplicate();
- item.top = base.top - config.vertical * (i + 1);
- item.left = base.left;
+ item.top = top - config.vertical * (i + 1);
+ item.left = left;
}
}
}
-function getConfig(dialog) {
- var units = getUnits(app.activeDocument.rulerUnits);
- var rows = Number(dialog.rows.text);
- var columns = Number(dialog.columns.text);
- var vertical = Number(dialog.vertical.text);
- var horizontal = Number(dialog.horizontal.text);
- return {
- mode: {
- grid: (dialog.grid.value) ? true : false,
- repeat: (dialog.grid.value) ? false : true
- },
- rows: isNaN(rows) ? 1 : rows,
- columns: isNaN(columns) ? 1 : columns,
- vertical: isNaN(vertical) ? 0 : convertUnits(vertical + units, 'pt'),
- horizontal: isNaN(horizontal) ? 0 : convertUnits(horizontal + units, 'pt')
- };
+function getValue(text) {
+ var twoByteChar = /[!-~]/g;
+ var value = text.replace(twoByteChar, function(str) {
+ return String.fromCharCode(str.charCodeAt(0) - 0xFEE0);
+ });
+ if (isNaN(value) || !value) return 0;
+ return Number(value);
}
-function getUnits(ruler) {
- switch (ruler) {
- case RulerUnits.Millimeters: return 'mm';
- case RulerUnits.Centimeters: return 'cm';
- case RulerUnits.Inches: return 'in';
- case RulerUnits.Points: return 'pt';
- case RulerUnits.Pixels: return 'px';
- default: return 'pt';
+function convertUnits(value, unit) {
+ try {
+ return Number(UnitValue(value).as(unit));
+ }
+ catch (err) {
+ return Number(UnitValue('1pt').as('pt'));
}
}
-function convertUnits(value, unit) {
+function getRulerUnits() {
+ var unit = getUnitSymbol();
+ if (!app.documents.length) return unit.pt;
+
+ var document = app.activeDocument;
+ var src = document.fullName;
+ var ruler = document.rulerUnits;
try {
- return Number(UnitValue(value).as(unit));
+ switch (ruler) {
+ case RulerUnits.Pixels: return unit.px;
+ case RulerUnits.Points: return unit.pt;
+ case RulerUnits.Picas: return unit.pc;
+ case RulerUnits.Inches: return unit.inch;
+ case RulerUnits.Millimeters: return unit.mm;
+ case RulerUnits.Centimeters: return unit.cm;
+
+ case RulerUnits.Feet: return unit.ft;
+ case RulerUnits.Yards: return unit.yd;
+ case RulerUnits.Meters: return unit.meter;
+ }
}
catch (err) {
- return Number(UnitValue('1pt').as('pt'));
+ switch (xmpRulerUnits(src)) {
+ case 'Feet': return unit.ft;
+ case 'Yards': return unit.yd;
+ case 'Meters': return unit.meter;
+ }
}
+ return unit.pt;
+}
+
+
+function xmpRulerUnits(src) {
+ if (!ExternalObject.AdobeXMPScript) {
+ ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
+ }
+ var xmpFile = new XMPFile(src.fsName, XMPConst.FILE_UNKNOWN, XMPConst.OPEN_FOR_READ);
+ var xmpPackets = xmpFile.getXMP();
+ var xmp = new XMPMeta(xmpPackets.serialize());
+
+ var namespace = 'http://ns.adobe.com/xap/1.0/t/pg/';
+ var prop = 'xmpTPg:MaxPageSize';
+ var unit = prop + '/stDim:unit';
+
+ var ruler = xmp.getProperty(namespace, unit).value;
+ return ruler;
+}
+
+
+function getUnitSymbol() {
+ return {
+ px: 'px',
+ pt: 'pt',
+ pc: 'pc',
+ inch: 'in',
+ ft: 'ft',
+ yd: 'yd',
+ mm: 'mm',
+ cm: 'cm',
+ meter: 'm'
+ };
}
function validate(config) {
if (config.rows < 1 || config.columns < 1) {
$.localize = true;
- alert(errorMessage(1));
+ var value = 1;
+ alert(errorMessage(value));
return false;
}
return true;
@@ -170,7 +245,15 @@ function errorMessage(value) {
}
-function showDialog() {
+function isValidVersion() {
+ var cs4 = 14;
+ var aiVersion = parseInt(app.version);
+ if (aiVersion < cs4) return false;
+ return true;
+}
+
+
+function showDialog(items) {
$.localize = true;
var ui = localizeUI();
var dialog = new Window('dialog');
@@ -307,15 +390,15 @@ function showDialog() {
var checkbox2 = group9.add('checkbox', undefined, undefined, { name: 'checkbox2' });
checkbox2.text = ui.preview;
- // Work around the problem of being unable to undo the ESC key during localization.
+ // Work around the problem of not being able to undo with the esc key due to localization.
var button3 = group9.add('button', undefined, undefined, { name: 'button3' });
button3.text = 'Cancel';
+ button3.preferredSize.height = 18;
button3.hide();
button3.onClick = function() {
if (checkbox2.value) {
- app.undo();
- app.redraw();
+ restore(items);
}
dialog.close();
}
@@ -331,25 +414,45 @@ function showDialog() {
statictext1.text = checkbox1.value ? ui.rows : ui.count;
edittext1.active = false;
edittext1.active = true;
- preview(dialog);
+ preview(dialog, items);
}
edittext1.onChanging = function() {
- preview(dialog);
+ preview(dialog, items);
}
edittext2.onChanging = function() {
- preview(dialog);
+ preview(dialog, items);
}
edittext3.onChanging = function() {
- preview(dialog);
+ preview(dialog, items);
}
edittext4.onChanging = function() {
- preview(dialog);
+ preview(dialog, items);
}
+ edittext1.addEventListener('keydown', function(event) {
+ setRepeatValue(event);
+ preview(dialog, items);
+ });
+
+ edittext2.addEventListener('keydown', function(event) {
+ setRepeatValue(event);
+ preview(dialog, items);
+ });
+
+ edittext3.addEventListener('keydown', function(event) {
+ setOffsetValue(event);
+ preview(dialog, items);
+ });
+
+ edittext4.addEventListener('keydown', function(event) {
+ setOffsetValue(event);
+ preview(dialog, items);
+ });
+
statictext1.addEventListener('click', function() {
edittext1.active = false;
edittext1.active = true;
@@ -381,6 +484,41 @@ function showDialog() {
}
+function setRepeatValue(event) {
+ var value = getValue(event.target.text);
+ var keyboard = ScriptUI.environment.keyboardState;
+ var step = keyboard.shiftKey ? 5 : 1;
+ if (event.keyName == 'Up') {
+ value += step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+ if (event.keyName == 'Down') {
+ value -= step;
+ if (value < 1) value = 1;
+ event.target.text = value;
+ event.preventDefault();
+ }
+}
+
+
+function setOffsetValue(event) {
+ var value = getValue(event.target.text);
+ var keyboard = ScriptUI.environment.keyboardState;
+ var step = keyboard.shiftKey ? 5 : 1;
+ if (event.keyName == 'Up') {
+ value += step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+ if (event.keyName == 'Down') {
+ value -= step;
+ event.target.text = value;
+ event.preventDefault();
+ }
+}
+
+
function localizeUI() {
return {
title: {