Copy link to clipboard
Copied
I'd love to see an option in preferences under Units and Rulers to set the Ruler Origin (0,0) to be in a different location than the top left corner of the artboard, either on a document by document basis, or as a default - maybe with a toggle. A 3x3 grid of radio button selections such as top left, middle left, bottom left; top center, middle center, bottom center; top right, middle right, bottom right would be ideal, but a drop down list would work also. This would save having to zoom waaaaayyy in to the appropriate location and dragging the corner box of the ruler to (hopefully) line up with the exact pixel you're aiming for on each new artboard/file.
If there's already a simple way to do this that I'm unaware of, I'd love to know what it is!
Thanks!
mscureman
If you want to submit the radio button/dropdown idea (I'd +1) it you can submit it here:
Thanks for the feedback, kstohlmeyer! I knew about dragging the upper left corner, but didn't know about the Shift key modifier. Helpful!
Also, I submitted this as an "Idea" on the feedback forum here:
Set Ruler Origin Location in Preferences, New Document Dialog or Menu
Copy link to clipboard
Copied
Its super easy to reorientate the ruler:
Grab the upper left corner where the two rulers meet and drag a new orientation point.
If you hold the shift key while you move it will lock to ruler positions.
Copy link to clipboard
Copied
If you want to submit the radio button/dropdown idea (I'd +1) it you can submit it here:
Copy link to clipboard
Copied
Thanks for the feedback, kstohlmeyer! I knew about dragging the upper left corner, but didn't know about the Shift key modifier. Helpful!
Also, I submitted this as an "Idea" on the feedback forum here:
Set Ruler Origin Location in Preferences, New Document Dialog or Menu
Copy link to clipboard
Copied
A similar topic here: Feature Request: Set Origin Point
Copy link to clipboard
Copied
I'd love to have an option to set where the 0,0 point is for the X and Y axes. Top Left is fine for many projects, but it'd be nice to have, perhaps, a radio button-style interface, either in preferences or in the document properties (or both!), where you had a 3x3 grid of buttons so you could choose to set the reference origin point at the:
Top Left, Top Middle, Top Right
Middle Left, Center, Middle Right
Bottom Left, Bottom Middle, Bottom Right
See attached photo
Copy link to clipboard
Copied
If you not already aware you can change the point of origin if you have View>Rulers enabled.
Grid, Guides, and Ruler Shortcuts in Photoshop
You can make a feature requst over here:
Copy link to clipboard
Copied
Thanks, Jeff. Yes, I'm aware of the feature to drag the origin point on the rulers, but that's the shortcut I'm looking for. I want a way to set that simply either as a default preference, or as a one-click solution on a per document basis. One of the major drawbacks to clicking and dragging is the need to zoom in to a high level in order to precisely set 0,0 at the exact corner.
Also, I realized that I posted this request in the feedback forum you linked to about a year ago. I'd forgotten that I'd done that, but the need keeps cropping up for me, so I posted again.
Copy link to clipboard
Copied
Thanks, Jeff. Yes, I'm aware of the feature to drag the origin point on the rulers, but that's the shortcut I'm looking for. I want a way to set that simply either as a default preference, or as a one-click solution on a per document basis. One of the major drawbacks to clicking and dragging is the need to zoom in to a high level in order to precisely set 0,0 at the exact corner.
By @mscureman
I realise this is an old thread, but this might help. I had an issue with Free Transform Step & Repeat where, if you did not precisely position the centre handle and the S&R had an angular component, even a slight error could cause the layers to walk away from being concentric. The minutes on a clock face being a good example, the 59 steps being enough to show a very obvious error by the last layer.
So what I do is drag guides to the document centre, which snap into place if snap is enabled. Guides also snap to document edges, or you can precisely place them with View > New Guide or New Guide Layout. The document origin will snap to guide intersections and you then have an option to precicely place centre handle in the Options Bar.
I'm thinking I should test it, so I have made a new guide layout using the margins set to 0%, and saved it as Perimeter.
You can save New Guide layouts with a meaningful name, and make a set of simple Actions that apply a saved guide layout, and drag the document origin to one of the corners, or centre, etc. ...and it didn't work. It produces the guide layout OK, but the Action did not record my dragging the origin to the lower left corner. I don't know of any way to move the origin other than dragging so that's a no go unless someone knows different? I bet @Stephen Marsh could do it? 🙂
You could still use an action top quickly place guides around the perimeter and centre. It would then only take a moment to drag the origin to any of those guide intersections, and it would be 100% accurate.
Copy link to clipboard
Copied
...but the Action did not record my dragging the origin to the lower left corner. I don't know of any way to move the origin other than dragging so that's a no go unless someone knows different? I bet @Stephen Marsh could do it? 🙂
By @Trevor.Dennis
Only by standing on the shoulders of @Tom Ruark !
The adaptations that I have created have all been driven by a GUI.
It should be simple enough to adapt to a hard-coded position that doesn't require user interaction, such as upper left, lower right, middle centre etc (one of the 9 standard location points on the canvas). This would be a useful "helper script" to call from an action. I have this on a "waiting list" for a community project that I haven't yet started.
Copy link to clipboard
Copied
Hi @mscureman
For the origin, Photoshop uses the same widget that InDesign and Illustrator use (plus other DTP applications going back 30+ years). Click the reference point to indicate the postion, then type the W and H in the options bar.
To move the zero point, drag from the intersection of the rulers. Double-click the intersection to put it back.
~ Jane
Copy link to clipboard
Copied
Thanks Jane, but I'm aware of the ability to drag the origin point. I realized that I'd already posted this request a year ago in the feedback forum, but the issue remains a problem for me for the reasons I listed in that post.
Set Ruler Origin Location in Preferences, New Document Dialog or Menu
Also, I'm not seeing that widget when I use the Shape Tool (which is what I'm assuming you're using in your photo).
Copy link to clipboard
Copied
Copy link to clipboard
Copied
I wanted to do so much more, however, I have hit problems (variables, scriptUI etc).
The following script will offer a horizontal and vertical prompt, where you can input pixel values. The default is upper left, absolute: 0, 0 (the default ruler origin zero point)
In the short term, it is simple enough to make 9 separate scripts for the various fixed positions on the canvas (middle centre, lower right etc). These could be recorded into an action for a "quick n dirty GUI" selector.
I'm sure it would also be possible to make the origin offset relative to the upper left of a selection, however that would be last on my list considering the other challenges that I have hit.
/*
https://community.adobe.com/t5/photoshop/feature-request-set-origin-point/td-p/12037399
Feature Request: Set Origin Point
Set Ruler Origin to User Input.jsx
Version 1.0, 15th May 2021
Stephen Marsh
*/
#target photoshop
if (app.documents.length > 0) {
(function () {
// Save the current ruler units and set to pixels
var savedRuler = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
////////////////////////////// tom_ruark @ adobe //////////////////////////////
/* https://feedback.photoshop.com/conversations/photoshop/photoshop-ability-to-ruler-origin-by-script/5f5f45bb4b561a3d425c7b32 */
// Version 2016.11.18
// Show how to get and set the ruler origin point for the current document
// Values are in pixels shifted 16 bits
// some constants to make it more readable
const classProperty = app.stringIDToTypeID("property");
const krulerOriginHStr = app.stringIDToTypeID("rulerOriginH");
const krulerOriginVStr = app.stringIDToTypeID("rulerOriginV");
const classDocument = app.stringIDToTypeID("document");
const typeOrdinal = app.stringIDToTypeID("ordinal");
const enumTarget = app.stringIDToTypeID("targetEnum");
const typeNULL = app.stringIDToTypeID("null");
const keyTo = app.stringIDToTypeID("to");
const eventSet = app.stringIDToTypeID("set");
// get the current values
GetRulerOrigin().toSource();
function GetRulerOrigin() {
var ro = {};
ro.horizontal = GetInfo(classDocument, krulerOriginHStr) >> 16;
ro.vertical = GetInfo(classDocument, krulerOriginVStr) >> 16;
return ro;
}
function SetRulerOrigin_Horiz(horiz) {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putProperty(classProperty, krulerOriginHStr);
ref.putEnumerated(classDocument, typeOrdinal, enumTarget);
desc.putReference(typeNULL, ref);
desc.putInteger(keyTo, horiz << 16);
executeAction(eventSet, desc, DialogModes.NO);
}
function SetRulerOrigin_Vert(vert) {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putProperty(classProperty, krulerOriginVStr);
ref.putEnumerated(classDocument, typeOrdinal, enumTarget);
desc.putReference(typeNULL, ref);
desc.putInteger(keyTo, vert << 16);
executeAction(eventSet, desc, DialogModes.NO);
}
///////////////////////////////////////////////////////////////////////////////
// Function: GetInfo
// Usage: Get information from Photoshop
// Input: desiredClass, classApplication, classLayer, etc.
// desiredKey, optional specific key to get instead of everything
// this is recommended as all keys is an expensive call
// Return: ActionDescriptor or single value depending on what is asked for
///////////////////////////////////////////////////////////////////////////////
function GetInfo(desiredClass, desiredKey) {
var reference = new ActionReference();
if (typeof desiredKey != "undefined") {
reference.putProperty(stringIDToTypeID("property"), desiredKey);
}
reference.putEnumerated(desiredClass, stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
var desc = executeActionGet(reference);
if (typeof desiredKey != "undefined") {
return GetItemFromDescriptor(desc, desiredKey);
}
return desc;
}
///////////////////////////////////////////////////////////////////////////////
// Function: GetItemFromDescriptor
// Usage: Get a specific key from an ActionDescriptor
// Input: desc (ActionDescriptor), valid ActionDescriptor to pull info from
// desiredKey (Number), key in question, use charIDToTypeID() or
// stringIDToTypeID()
// Return: ActionDescriptor or single value depending on what is asked for
///////////////////////////////////////////////////////////////////////////////
function GetItemFromDescriptor(desc, desiredKey) {
if (desc.hasKey(desiredKey)) {
var typeID = desc.getType(desiredKey);
switch (typeID) {
case DescValueType.BOOLEANTYPE:
return desc.getBoolean(desiredKey);
break;
case DescValueType.STRINGTYPE:
return desc.getString(desiredKey);
break;
case DescValueType.DOUBLETYPE:
return desc.getDouble(desiredKey);
break;
case DescValueType.INTEGERTYPE:
return desc.getInteger(desiredKey);
break;
case DescValueType.LARGEINTEGERTYPE:
return desc.getLargeInteger(desiredKey);
break;
case DescValueType.OBJECTTYPE:
return desc.getObjectValue(desiredKey);
break;
case DescValueType.UNITDOUBLE:
var newT = desc.getUnitDoubleType(desiredKey);
var newV = desc.getUnitDoubleValue(desiredKey);
return new UnitValue(newV, newT);
break;
case DescValueType.ENUMERATEDTYPE:
return desc.getEnumerationValue(desiredKey);
break;
case DescValueType.CLASSTYPE:
return desc.getClass(desiredKey);
break;
case DescValueType.ALIASTYPE:
return desc.getPath(desiredKey);
break;
case DescValueType.RAWTYPE:
var tempStr = desc.getData(desiredKey);
var rawData = new Array();
for (var tempi = 0; tempi < tempStr.length; tempi++) {
rawData[tempi] = tempStr.charCodeAt(tempi);
}
return rawData;
break;
case DescValueType.REFERENCETYPE:
return desc.getReference(desiredKey);
break;
case DescValueType.LISTTYPE:
return desc.getList(desiredKey);
break;
default:
return;
}
}
return;
}
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
////////////////////////////// tom_ruark @ adobe //////////////////////////////
// Horizontal Input
// Loop the input prompt until a number is entered
var horizInput;
while (isNaN(horizInput = prompt("Horizontal origin in pixels:", "0")));
// Test if cancel returns null, then terminate the script
if (horizInput === null) {
alert('Script cancelled!');
return
}
// Test if an empty string is returned, then terminate the script
if (horizInput === "") {
alert('A value was not entered, script cancelled!');
return
}
// Convert decimal input to integer
var horizToInteger = parseInt(horizInput);
// Vertical Input
// Loop the input prompt until a number is entered
var vertInput;
while (isNaN(vertInput = prompt("Vertical origin in pixels:", "0")));
// Test if cancel returns null, then terminate the script
if (vertInput === null) {
alert('Script cancelled!');
return
}
// Test if an empty string is returned, then terminate the script
if (vertInput === "") {
alert('A value was not entered, script cancelled!');
return
}
// Convert decimal input to integer
var vertToInteger = parseInt(vertInput);
// Set the origin from the prompts
SetRulerOrigin_Horiz(horizToInteger);
SetRulerOrigin_Vert(vertToInteger);
// Restore the ruler units
app.preferences.rulerUnits = savedRuler;
})
();
}
else {
alert('A document must be open to use this script!');
}
https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html
Copy link to clipboard
Copied
I believe that I have overcome the previous "basic" challenges with adding the GUI to the script code...
/*
https://community.adobe.com/t5/photoshop/feature-request-set-origin-point/td-p/12037399
Feature Request: Set Origin Point
Set Ruler Origin to User Input.jsx
Version 1.1, 16th May 2021
Stephen Marsh
*/
#target photoshop
if (app.documents.length > 0) {
// Save the current ruler units and set to pixels
var savedRuler = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
/////////////////////////////// joonas scriptUI ///////////////////////////////
/*
Code for Import https://scriptui.joonas.me — (Triple click to select):
{"activeId":0,"items":{"item-0":{"id":0,"type":"Dialog","parentId":false,"style":{"enabled":true,"varName":"dialogWindow","windowType":"Dialog","creationProps":{"su1PanelCoordinates":false,"maximizeButton":false,"minimizeButton":false,"independent":false,"closeButton":false,"borderless":false,"resizeable":false},"text":"Set Ruler Origin","preferredSize":[410,100],"margins":15,"orientation":"row","spacing":10,"alignChildren":["left","top"]}},"item-2":{"id":2,"type":"Button","parentId":4,"style":{"enabled":true,"varName":"okButton","text":"OK","justify":"center","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-3":{"id":3,"type":"Button","parentId":4,"style":{"enabled":true,"varName":"cancelButton","text":"Cancel","justify":"center","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-4":{"id":4,"type":"Group","parentId":0,"style":{"enabled":true,"varName":"okGroup","preferredSize":[0,0],"margins":[1,1,1,10],"orientation":"column","spacing":12,"alignChildren":["left","top"],"alignment":"top"}},"item-5":{"id":5,"type":"Group","parentId":0,"style":{"enabled":true,"varName":"upperGroup","preferredSize":[0,0],"margins":0,"orientation":"column","spacing":10,"alignChildren":["left","center"],"alignment":null}},"item-6":{"id":6,"type":"RadioButton","parentId":5,"style":{"enabled":true,"varName":"upperLeft","text":"Upper Left","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-7":{"id":7,"type":"RadioButton","parentId":5,"style":{"enabled":true,"varName":"middleLeft","text":"Middle Left","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-8":{"id":8,"type":"RadioButton","parentId":5,"style":{"enabled":true,"varName":"lowerLeft","text":"Lower Left","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-9":{"id":9,"type":"Group","parentId":0,"style":{"enabled":true,"varName":"middleGroup","preferredSize":[0,0],"margins":0,"orientation":"column","spacing":10,"alignChildren":["left","center"],"alignment":null}},"item-10":{"id":10,"type":"RadioButton","parentId":9,"style":{"enabled":true,"varName":"upperCenter","text":"Upper Center","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-11":{"id":11,"type":"RadioButton","parentId":9,"style":{"enabled":true,"varName":"middleCenter","text":"Middle Center","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-12":{"id":12,"type":"RadioButton","parentId":9,"style":{"enabled":true,"varName":"lowerCenter","text":"Lower Center","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-13":{"id":13,"type":"Group","parentId":0,"style":{"enabled":true,"varName":"lowerGroup","preferredSize":[0,0],"margins":0,"orientation":"column","spacing":10,"alignChildren":["left","center"],"alignment":null}},"item-14":{"id":14,"type":"RadioButton","parentId":13,"style":{"enabled":true,"varName":"upperRight","text":"Upper Right","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-15":{"id":15,"type":"RadioButton","parentId":13,"style":{"enabled":true,"varName":"middleRight","text":"Middle Right","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-16":{"id":16,"type":"RadioButton","parentId":13,"style":{"enabled":true,"varName":"lowerRight","text":"Lower Right","preferredSize":[0,0],"alignment":null,"helpTip":null}}},"order":[0,5,6,7,8,9,10,11,12,13,14,15,16,4,2,3],"settings":{"importJSON":true,"indentSize":false,"cepExport":false,"includeCSSJS":true,"showDialog":true,"functionWrapper":false,"afterEffectsDockable":false,"itemReferenceList":"None"}}
*/
// DIALOGWINDOW
// ============
var dialogWindow = new Window("dialog", undefined, undefined, { closeButton: false });
dialogWindow.text = "Set Ruler Origin - v1.1";
dialogWindow.preferredSize.width = 410;
dialogWindow.preferredSize.height = 100;
dialogWindow.orientation = "row";
dialogWindow.alignChildren = ["left", "top"];
dialogWindow.spacing = 10;
dialogWindow.margins = 15;
// UPPERGROUP
// ==========
var upperGroup = dialogWindow.add("group", undefined, { name: "upperGroup" });
upperGroup.orientation = "column";
upperGroup.alignChildren = ["left", "center"];
upperGroup.spacing = 10;
upperGroup.margins = 0;
var upperLeft = upperGroup.add("radiobutton", undefined, undefined, { name: "upperLeft" });
upperLeft.text = "Upper Left";
var middleLeft = upperGroup.add("radiobutton", undefined, undefined, { name: "middleLeft" });
middleLeft.text = "Middle Left";
var lowerLeft = upperGroup.add("radiobutton", undefined, undefined, { name: "lowerLeft" });
lowerLeft.text = "Lower Left";
////////////////////// peter kahrel scriptUI for dummies //////////////////////
// Preset the upper left radiobutton as active
upperGroup.children[0].value = true;
////////////////////// peter kahrel scriptUI for dummies //////////////////////
// MIDDLEGROUP
// ===========
var middleGroup = dialogWindow.add("group", undefined, { name: "middleGroup" });
middleGroup.orientation = "column";
middleGroup.alignChildren = ["left", "center"];
middleGroup.spacing = 10;
middleGroup.margins = 0;
var upperCenter = middleGroup.add("radiobutton", undefined, undefined, { name: "upperCenter" });
upperCenter.text = "Upper Center";
var middleCenter = middleGroup.add("radiobutton", undefined, undefined, { name: "middleCenter" });
middleCenter.text = "Middle Center";
var lowerCenter = middleGroup.add("radiobutton", undefined, undefined, { name: "lowerCenter" });
lowerCenter.text = "Lower Center";
// LOWERGROUP
// ==========
var lowerGroup = dialogWindow.add("group", undefined, { name: "lowerGroup" });
lowerGroup.orientation = "column";
lowerGroup.alignChildren = ["left", "center"];
lowerGroup.spacing = 10;
lowerGroup.margins = 0;
var upperRight = lowerGroup.add("radiobutton", undefined, undefined, { name: "upperRight" });
upperRight.text = "Upper Right";
var middleRight = lowerGroup.add("radiobutton", undefined, undefined, { name: "middleRight" });
middleRight.text = "Middle Right";
var lowerRight = lowerGroup.add("radiobutton", undefined, undefined, { name: "lowerRight" });
lowerRight.text = "Lower Right";
// OKGROUP
// =======
var okGroup = dialogWindow.add("group", undefined, { name: "okGroup" });
okGroup.orientation = "column";
okGroup.alignChildren = ["left", "top"];
okGroup.spacing = 12;
okGroup.margins = [10, 1, 1, 1];
okGroup.alignment = ["left", "top"];
var okButton = okGroup.add("button", undefined, undefined, { name: "okButton" });
okButton.text = "OK";
var cancelButton = okGroup.add("button", undefined, undefined, { name: "cancelButton" });
cancelButton.text = "Cancel";
/////////////////////////////// joonas scriptUI ///////////////////////////////
////////////////////////////// tom_ruark @ adobe //////////////////////////////
/* https://feedback.photoshop.com/conversations/photoshop/photoshop-ability-to-ruler-origin-by-script/5f5f45bb4b561a3d425c7b32 */
// Version 2016.11.18
// Show how to get and set the ruler origin point for the current document
// Values are in pixels shifted 16 bits
// some constants to make it more readable
const classProperty = app.stringIDToTypeID("property");
const krulerOriginHStr = app.stringIDToTypeID("rulerOriginH");
const krulerOriginVStr = app.stringIDToTypeID("rulerOriginV");
const classDocument = app.stringIDToTypeID("document");
const typeOrdinal = app.stringIDToTypeID("ordinal");
const enumTarget = app.stringIDToTypeID("targetEnum");
const typeNULL = app.stringIDToTypeID("null");
const keyTo = app.stringIDToTypeID("to");
const eventSet = app.stringIDToTypeID("set");
// get the current values
GetRulerOrigin().toSource();
function GetRulerOrigin() {
var ro = {};
ro.horizontal = GetInfo(classDocument, krulerOriginHStr) >> 16;
ro.vertical = GetInfo(classDocument, krulerOriginVStr) >> 16;
return ro;
}
function SetRulerOrigin_Horiz(horiz) {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putProperty(classProperty, krulerOriginHStr);
ref.putEnumerated(classDocument, typeOrdinal, enumTarget);
desc.putReference(typeNULL, ref);
desc.putInteger(keyTo, horiz << 16);
executeAction(eventSet, desc, DialogModes.NO);
}
function SetRulerOrigin_Vert(vert) {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putProperty(classProperty, krulerOriginVStr);
ref.putEnumerated(classDocument, typeOrdinal, enumTarget);
desc.putReference(typeNULL, ref);
desc.putInteger(keyTo, vert << 16);
executeAction(eventSet, desc, DialogModes.NO);
}
///////////////////////////////////////////////////////////////////////////////
// Function: GetInfo
// Usage: Get information from Photoshop
// Input: desiredClass, classApplication, classLayer, etc.
// desiredKey, optional specific key to get instead of everything
// this is recommended as all keys is an expensive call
// Return: ActionDescriptor or single value depending on what is asked for
///////////////////////////////////////////////////////////////////////////////
function GetInfo(desiredClass, desiredKey) {
var reference = new ActionReference();
if (typeof desiredKey != "undefined") {
reference.putProperty(stringIDToTypeID("property"), desiredKey);
}
reference.putEnumerated(desiredClass, stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
var desc = executeActionGet(reference);
if (typeof desiredKey != "undefined") {
return GetItemFromDescriptor(desc, desiredKey);
}
return desc;
}
///////////////////////////////////////////////////////////////////////////////
// Function: GetItemFromDescriptor
// Usage: Get a specific key from an ActionDescriptor
// Input: desc (ActionDescriptor), valid ActionDescriptor to pull info from
// desiredKey (Number), key in question, use charIDToTypeID() or
// stringIDToTypeID()
// Return: ActionDescriptor or single value depending on what is asked for
///////////////////////////////////////////////////////////////////////////////
function GetItemFromDescriptor(desc, desiredKey) {
if (desc.hasKey(desiredKey)) {
var typeID = desc.getType(desiredKey);
switch (typeID) {
case DescValueType.BOOLEANTYPE:
return desc.getBoolean(desiredKey);
break;
case DescValueType.STRINGTYPE:
return desc.getString(desiredKey);
break;
case DescValueType.DOUBLETYPE:
return desc.getDouble(desiredKey);
break;
case DescValueType.INTEGERTYPE:
return desc.getInteger(desiredKey);
break;
case DescValueType.LARGEINTEGERTYPE:
return desc.getLargeInteger(desiredKey);
break;
case DescValueType.OBJECTTYPE:
return desc.getObjectValue(desiredKey);
break;
case DescValueType.UNITDOUBLE:
var newT = desc.getUnitDoubleType(desiredKey);
var newV = desc.getUnitDoubleValue(desiredKey);
return new UnitValue(newV, newT);
break;
case DescValueType.ENUMERATEDTYPE:
return desc.getEnumerationValue(desiredKey);
break;
case DescValueType.CLASSTYPE:
return desc.getClass(desiredKey);
break;
case DescValueType.ALIASTYPE:
return desc.getPath(desiredKey);
break;
case DescValueType.RAWTYPE:
var tempStr = desc.getData(desiredKey);
var rawData = new Array();
for (var tempi = 0; tempi < tempStr.length; tempi++) {
rawData[tempi] = tempStr.charCodeAt(tempi);
}
return rawData;
break;
case DescValueType.REFERENCETYPE:
return desc.getReference(desiredKey);
break;
case DescValueType.LISTTYPE:
return desc.getList(desiredKey);
break;
default:
return;
}
}
return;
}
////////////////////////////// tom_ruark @ adobe //////////////////////////////
/////////////////////////////// joonas scriptUI ///////////////////////////////
okButton.onClick = function () {
dialogWindow.close();
// Canvas variables
var rE = app.activeDocument.width; // rightEdge
var hC = app.activeDocument.width / 2; // horizontalCenter
var vC = app.activeDocument.height / 2; // verticalCenter
var bE = app.activeDocument.height; // bottomEdge
// Link function parameters to radio buttons
if (upperLeft.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
}
if (upperCenter.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(hC);
SetRulerOrigin_Vert(0);
}
if (upperRight.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(rE);
SetRulerOrigin_Vert(0);
}
if (middleLeft.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(vC);
}
if (middleCenter.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(hC);
SetRulerOrigin_Vert(vC);
}
if (middleRight.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(rE);
SetRulerOrigin_Vert(vC);
}
if (lowerLeft.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(bE);
}
if (lowerCenter.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(hC);
SetRulerOrigin_Vert(bE);
}
if (lowerRight.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(rE);
SetRulerOrigin_Vert(bE);
}
}
// Execute window
dialogWindow.show();
/////////////////////////////// joonas scriptUI ///////////////////////////////
// Restore the ruler units
app.preferences.rulerUnits = savedRuler;
}
else {
alert('A document must be open to use this script!');
}
Copy link to clipboard
Copied
NOTE: I can't edit my previous post, it just comes up with a blank field (I have tried two different browsers on the Mac). Strangely, I can edit this post, go figure!
A revised 1.2 version is below, which fixes the issues with the radio button groups in the 1.1 code!
/*
https://community.adobe.com/t5/photoshop/feature-request-set-origin-point/td-p/12037399
Feature Request: Set Origin Point
Set Ruler Origin to User Input.jsx
Version 1.2, 16th May 2021
Stephen Marsh
*/
#target photoshop
if (app.documents.length > 0) {
// Save the current ruler units and set to pixels
var savedRuler = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
/////////////////////////////// joonas scriptUI ///////////////////////////////
/*
Code for Import https://scriptui.joonas.me — (Triple click to select):
{"activeId":0,"items":{"item-0":{"id":0,"type":"Dialog","parentId":false,"style":{"enabled":true,"varName":"dialogWindow","windowType":"Dialog","creationProps":{"su1PanelCoordinates":false,"maximizeButton":false,"minimizeButton":false,"independent":false,"closeButton":false,"borderless":false,"resizeable":false},"text":"Set Ruler Origin","preferredSize":[410,100],"margins":15,"orientation":"row","spacing":10,"alignChildren":["left","top"]}},"item-2":{"id":2,"type":"Button","parentId":4,"style":{"enabled":true,"varName":"okButton","text":"OK","justify":"center","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-3":{"id":3,"type":"Button","parentId":4,"style":{"enabled":true,"varName":"cancelButton","text":"Cancel","justify":"center","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-4":{"id":4,"type":"Group","parentId":0,"style":{"enabled":true,"varName":"okGroup","preferredSize":[0,0],"margins":[1,1,1,10],"orientation":"column","spacing":12,"alignChildren":["left","top"],"alignment":"top"}},"item-5":{"id":5,"type":"Group","parentId":0,"style":{"enabled":true,"varName":"upperGroup","preferredSize":[0,0],"margins":0,"orientation":"column","spacing":10,"alignChildren":["left","center"],"alignment":null}},"item-6":{"id":6,"type":"RadioButton","parentId":5,"style":{"enabled":true,"varName":"upperLeft","text":"Upper Left","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-7":{"id":7,"type":"RadioButton","parentId":5,"style":{"enabled":true,"varName":"middleLeft","text":"Middle Left","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-8":{"id":8,"type":"RadioButton","parentId":5,"style":{"enabled":true,"varName":"lowerLeft","text":"Lower Left","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-9":{"id":9,"type":"Group","parentId":0,"style":{"enabled":true,"varName":"middleGroup","preferredSize":[0,0],"margins":0,"orientation":"column","spacing":10,"alignChildren":["left","center"],"alignment":null}},"item-10":{"id":10,"type":"RadioButton","parentId":9,"style":{"enabled":true,"varName":"upperCenter","text":"Upper Center","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-11":{"id":11,"type":"RadioButton","parentId":9,"style":{"enabled":true,"varName":"middleCenter","text":"Middle Center","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-12":{"id":12,"type":"RadioButton","parentId":9,"style":{"enabled":true,"varName":"lowerCenter","text":"Lower Center","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-13":{"id":13,"type":"Group","parentId":0,"style":{"enabled":true,"varName":"lowerGroup","preferredSize":[0,0],"margins":0,"orientation":"column","spacing":10,"alignChildren":["left","center"],"alignment":null}},"item-14":{"id":14,"type":"RadioButton","parentId":13,"style":{"enabled":true,"varName":"upperRight","text":"Upper Right","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-15":{"id":15,"type":"RadioButton","parentId":13,"style":{"enabled":true,"varName":"middleRight","text":"Middle Right","preferredSize":[0,0],"alignment":null,"helpTip":null}},"item-16":{"id":16,"type":"RadioButton","parentId":13,"style":{"enabled":true,"varName":"lowerRight","text":"Lower Right","preferredSize":[0,0],"alignment":null,"helpTip":null}}},"order":[0,5,6,7,8,9,10,11,12,13,14,15,16,4,2,3],"settings":{"importJSON":true,"indentSize":false,"cepExport":false,"includeCSSJS":true,"showDialog":true,"functionWrapper":false,"afterEffectsDockable":false,"itemReferenceList":"None"}}
*/
// DIALOGWINDOW
// ============
var dialogWindow = new Window("dialog", undefined, undefined, { closeButton: false });
dialogWindow.text = "Set Ruler Origin - v1.1";
dialogWindow.preferredSize.width = 410;
dialogWindow.preferredSize.height = 100;
dialogWindow.orientation = "row";
dialogWindow.alignChildren = ["left", "top"];
dialogWindow.spacing = 10;
dialogWindow.margins = 15;
// UPPERGROUP
// ==========
var upperGroup = dialogWindow.add("group", undefined, { name: "upperGroup" });
upperGroup.orientation = "column";
upperGroup.alignChildren = ["left", "center"];
upperGroup.spacing = 10;
upperGroup.margins = 0;
var upperLeft = upperGroup.add("radiobutton", undefined, undefined, { name: "upperLeft" });
upperLeft.text = "Upper Left";
var middleLeft = upperGroup.add("radiobutton", undefined, undefined, { name: "middleLeft" });
middleLeft.text = "Middle Left";
var lowerLeft = upperGroup.add("radiobutton", undefined, undefined, { name: "lowerLeft" });
lowerLeft.text = "Lower Left";
////////////////////// peter kahrel scriptUI for dummies //////////////////////
// Preset the upper left radiobutton as active
upperGroup.children[0].value = true;
////////////////////// peter kahrel scriptUI for dummies //////////////////////
// MIDDLEGROUP
// ===========
var middleGroup = dialogWindow.add("group", undefined, { name: "middleGroup" });
middleGroup.orientation = "column";
middleGroup.alignChildren = ["left", "center"];
middleGroup.spacing = 10;
middleGroup.margins = 0;
var upperCenter = middleGroup.add("radiobutton", undefined, undefined, { name: "upperCenter" });
upperCenter.text = "Upper Center";
var middleCenter = middleGroup.add("radiobutton", undefined, undefined, { name: "middleCenter" });
middleCenter.text = "Middle Center";
var lowerCenter = middleGroup.add("radiobutton", undefined, undefined, { name: "lowerCenter" });
lowerCenter.text = "Lower Center";
// LOWERGROUP
// ==========
var lowerGroup = dialogWindow.add("group", undefined, { name: "lowerGroup" });
lowerGroup.orientation = "column";
lowerGroup.alignChildren = ["left", "center"];
lowerGroup.spacing = 10;
lowerGroup.margins = 0;
var upperRight = lowerGroup.add("radiobutton", undefined, undefined, { name: "upperRight" });
upperRight.text = "Upper Right";
var middleRight = lowerGroup.add("radiobutton", undefined, undefined, { name: "middleRight" });
middleRight.text = "Middle Right";
var lowerRight = lowerGroup.add("radiobutton", undefined, undefined, { name: "lowerRight" });
lowerRight.text = "Lower Right";
////////////////////// peter kahrel scriptUI for dummies //////////////////////
upperGroup.addEventListener("click", function () {
for (var i = 0; i < middleGroup.children.length; i++)
middleGroup.children[i].value = false;
}
);
upperGroup.addEventListener("click", function () {
for (var i = 0; i < lowerGroup.children.length; i++)
lowerGroup.children[i].value = false;
}
);
middleGroup.addEventListener("click", function () {
for (var i = 0; i < upperGroup.children.length; i++)
upperGroup.children[i].value = false;
}
);
middleGroup.addEventListener("click", function () {
for (var i = 0; i < lowerGroup.children.length; i++)
lowerGroup.children[i].value = false;
}
);
lowerGroup.addEventListener("click", function () {
for (var i = 0; i < middleGroup.children.length; i++)
middleGroup.children[i].value = false;
}
);
lowerGroup.addEventListener("click", function () {
for (var i = 0; i < upperGroup.children.length; i++)
upperGroup.children[i].value = false;
}
);
////////////////////// peter kahrel scriptUI for dummies //////////////////////
/////////////////////////////// joonas scriptUI ///////////////////////////////
// OKGROUP
// =======
var okGroup = dialogWindow.add("group", undefined, { name: "okGroup" });
okGroup.orientation = "column";
okGroup.alignChildren = ["left", "top"];
okGroup.spacing = 12;
okGroup.margins = [10, 1, 1, 1];
okGroup.alignment = ["left", "top"];
var okButton = okGroup.add("button", undefined, undefined, { name: "okButton" });
okButton.text = "OK";
var cancelButton = okGroup.add("button", undefined, undefined, { name: "cancelButton" });
cancelButton.text = "Cancel";
/////////////////////////////// joonas scriptUI ///////////////////////////////
////////////////////////////// tom_ruark @ adobe //////////////////////////////
/* https://feedback.photoshop.com/conversations/photoshop/photoshop-ability-to-ruler-origin-by-script/5f5f45bb4b561a3d425c7b32 */
// Version 2016.11.18
// Show how to get and set the ruler origin point for the current document
// Values are in pixels shifted 16 bits
// some constants to make it more readable
const classProperty = app.stringIDToTypeID("property");
const krulerOriginHStr = app.stringIDToTypeID("rulerOriginH");
const krulerOriginVStr = app.stringIDToTypeID("rulerOriginV");
const classDocument = app.stringIDToTypeID("document");
const typeOrdinal = app.stringIDToTypeID("ordinal");
const enumTarget = app.stringIDToTypeID("targetEnum");
const typeNULL = app.stringIDToTypeID("null");
const keyTo = app.stringIDToTypeID("to");
const eventSet = app.stringIDToTypeID("set");
// get the current values
GetRulerOrigin().toSource();
function GetRulerOrigin() {
var ro = {};
ro.horizontal = GetInfo(classDocument, krulerOriginHStr) >> 16;
ro.vertical = GetInfo(classDocument, krulerOriginVStr) >> 16;
return ro;
}
function SetRulerOrigin_Horiz(horiz) {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putProperty(classProperty, krulerOriginHStr);
ref.putEnumerated(classDocument, typeOrdinal, enumTarget);
desc.putReference(typeNULL, ref);
desc.putInteger(keyTo, horiz << 16);
executeAction(eventSet, desc, DialogModes.NO);
}
function SetRulerOrigin_Vert(vert) {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putProperty(classProperty, krulerOriginVStr);
ref.putEnumerated(classDocument, typeOrdinal, enumTarget);
desc.putReference(typeNULL, ref);
desc.putInteger(keyTo, vert << 16);
executeAction(eventSet, desc, DialogModes.NO);
}
///////////////////////////////////////////////////////////////////////////////
// Function: GetInfo
// Usage: Get information from Photoshop
// Input: desiredClass, classApplication, classLayer, etc.
// desiredKey, optional specific key to get instead of everything
// this is recommended as all keys is an expensive call
// Return: ActionDescriptor or single value depending on what is asked for
///////////////////////////////////////////////////////////////////////////////
function GetInfo(desiredClass, desiredKey) {
var reference = new ActionReference();
if (typeof desiredKey != "undefined") {
reference.putProperty(stringIDToTypeID("property"), desiredKey);
}
reference.putEnumerated(desiredClass, stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
var desc = executeActionGet(reference);
if (typeof desiredKey != "undefined") {
return GetItemFromDescriptor(desc, desiredKey);
}
return desc;
}
///////////////////////////////////////////////////////////////////////////////
// Function: GetItemFromDescriptor
// Usage: Get a specific key from an ActionDescriptor
// Input: desc (ActionDescriptor), valid ActionDescriptor to pull info from
// desiredKey (Number), key in question, use charIDToTypeID() or
// stringIDToTypeID()
// Return: ActionDescriptor or single value depending on what is asked for
///////////////////////////////////////////////////////////////////////////////
function GetItemFromDescriptor(desc, desiredKey) {
if (desc.hasKey(desiredKey)) {
var typeID = desc.getType(desiredKey);
switch (typeID) {
case DescValueType.BOOLEANTYPE:
return desc.getBoolean(desiredKey);
break;
case DescValueType.STRINGTYPE:
return desc.getString(desiredKey);
break;
case DescValueType.DOUBLETYPE:
return desc.getDouble(desiredKey);
break;
case DescValueType.INTEGERTYPE:
return desc.getInteger(desiredKey);
break;
case DescValueType.LARGEINTEGERTYPE:
return desc.getLargeInteger(desiredKey);
break;
case DescValueType.OBJECTTYPE:
return desc.getObjectValue(desiredKey);
break;
case DescValueType.UNITDOUBLE:
var newT = desc.getUnitDoubleType(desiredKey);
var newV = desc.getUnitDoubleValue(desiredKey);
return new UnitValue(newV, newT);
break;
case DescValueType.ENUMERATEDTYPE:
return desc.getEnumerationValue(desiredKey);
break;
case DescValueType.CLASSTYPE:
return desc.getClass(desiredKey);
break;
case DescValueType.ALIASTYPE:
return desc.getPath(desiredKey);
break;
case DescValueType.RAWTYPE:
var tempStr = desc.getData(desiredKey);
var rawData = new Array();
for (var tempi = 0; tempi < tempStr.length; tempi++) {
rawData[tempi] = tempStr.charCodeAt(tempi);
}
return rawData;
break;
case DescValueType.REFERENCETYPE:
return desc.getReference(desiredKey);
break;
case DescValueType.LISTTYPE:
return desc.getList(desiredKey);
break;
default:
return;
}
}
return;
}
////////////////////////////// tom_ruark @ adobe //////////////////////////////
/////////////////////////////// joonas scriptUI ///////////////////////////////
okButton.onClick = function () {
dialogWindow.close();
// Canvas variables
var rE = app.activeDocument.width; // rightEdge
var hC = app.activeDocument.width / 2; // horizontalCenter
var vC = app.activeDocument.height / 2; // verticalCenter
var bE = app.activeDocument.height; // bottomEdge
// Link function parameters to radio buttons
if (upperLeft.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
}
if (upperCenter.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(hC);
SetRulerOrigin_Vert(0);
}
if (upperRight.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(rE);
SetRulerOrigin_Vert(0);
}
if (middleLeft.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(vC);
}
if (middleCenter.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(hC);
SetRulerOrigin_Vert(vC);
}
if (middleRight.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(rE);
SetRulerOrigin_Vert(vC);
}
if (lowerLeft.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(bE);
}
if (lowerCenter.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(hC);
SetRulerOrigin_Vert(bE);
}
if (lowerRight.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(rE);
SetRulerOrigin_Vert(bE);
}
}
// Execute window
dialogWindow.show();
/////////////////////////////// joonas scriptUI ///////////////////////////////
// Restore the ruler units
app.preferences.rulerUnits = savedRuler;
}
else {
alert('A document must be open to use this script!');
}
Copy link to clipboard
Copied
I worked out a wee workaround a few years ago after having problems with free transform step and repeat. I was making a clock face, and because the origin point will not snap to a guide intersection, by the time you'd made your twelve FT rotations the build up of error was causing visible misalignment.
I realsed that while the origin would not snap to a guide interesction, it would snap to a pixel location, so the answer was to place the guides and drag the grid zero to the guide intersection, (that does snap). Then when using FT rotate, Alt drag the origin close to 0,0 and then correct it in the Options bar. If you then use step and repeat 12 times, the last one will align perfectly with the first.
Copy link to clipboard
Copied
I've worded that wrong. The origin does not snap to the grid zoro, zero, but the grid 0,0 will snap to the guide interection.
Copy link to clipboard
Copied
If you hold down the Shift key while moving the Point of Orin it will snap to the ruler tick marks.
Copy link to clipboard
Copied
NOTE: It appears that adding the joonas JSON code makes the previous scripts that I posted uneditable with this forum software, good to know!
Copy link to clipboard
Copied
Is there any interest in extending the previous script to offer X/Y co-ordinate entry fields, in addition to the 9 preset locations?
Copy link to clipboard
Copied
Here is a new 1.3 version, including X & Y entry fields in addition to the original 9 preset locations. The intention/expectation is that either the radio buttons are used, or the fields are used instead - not both at the same time. There may be a way to make the use of one disable the other?
Set-Ruler-Origin-to-User-Input-GUI.jsx
Set-Ruler-Origin-to-User-Input-GUI.jsx
/*
https://community.adobe.com/t5/photoshop/feature-request-set-origin-point/td-p/12037399
Feature Request: Set Origin Point
Set Ruler Origin to User Input.jsx
Version 1.3, 19th May 2021
Stephen Marsh
*/
#target photoshop
if (app.documents.length > 0) {
// Save the current ruler units and set to pixels
var savedRuler = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.PIXELS;
/////////////////////////////// joonas scriptUI ///////////////////////////////
// DIALOGWINDOW
// ============
var dialogWindow = new Window("dialog", undefined, undefined, {
closeButton: false
});
dialogWindow.text = "Set Ruler Origin - v1.3"; // Remember to update this to match the header!
dialogWindow.preferredSize.width = 410;
dialogWindow.preferredSize.height = 100;
dialogWindow.orientation = "row";
dialogWindow.alignChildren = ["left", "center"];
dialogWindow.spacing = 10;
dialogWindow.margins = 15;
// GROUP1
// ======
var group1 = dialogWindow.add("group", undefined, {
name: "group1"
});
group1.orientation = "row";
group1.alignChildren = ["left", "center"];
group1.spacing = 10;
group1.margins = 0;
// UPPERGROUP
// ==========
var upperGroup = group1.add("group", undefined, {
name: "upperGroup"
});
upperGroup.orientation = "column";
upperGroup.alignChildren = ["left", "center"];
upperGroup.spacing = 10;
upperGroup.margins = 0;
var upperLeft = upperGroup.add("radiobutton", undefined, undefined, {
name: "upperLeft"
});
upperLeft.text = "Upper Left";
upperLeft.helpTip = "Radio buttons override the X & Y fields";
var middleLeft = upperGroup.add("radiobutton", undefined, undefined, {
name: "middleLeft"
});
middleLeft.text = "Middle Left";
middleLeft.helpTip = "Radio buttons override the X & Y fields";
var lowerLeft = upperGroup.add("radiobutton", undefined, undefined, {
name: "lowerLeft"
});
lowerLeft.text = "Lower Left";
lowerLeft.helpTip = "Radio buttons override the X & Y fields";
// MIDDLEGROUP
// ===========
var middleGroup = group1.add("group", undefined, {
name: "middleGroup"
});
middleGroup.orientation = "column";
middleGroup.alignChildren = ["left", "center"];
middleGroup.spacing = 10;
middleGroup.margins = 0;
var upperCenter = middleGroup.add("radiobutton", undefined, undefined, {
name: "upperCenter"
});
upperCenter.text = "Upper Center";
upperCenter.helpTip = "Radio buttons override the X & Y fields";
var middleCenter = middleGroup.add("radiobutton", undefined, undefined, {
name: "middleCenter"
});
middleCenter.text = "Middle Center";
middleCenter.helpTip = "Radio buttons override the X & Y fields";
var lowerCenter = middleGroup.add("radiobutton", undefined, undefined, {
name: "lowerCenter"
});
lowerCenter.text = "Lower Center";
lowerCenter.helpTip = "Radio buttons override the X & Y fields";
// LOWERGROUP
// ==========
var lowerGroup = group1.add("group", undefined, {
name: "lowerGroup"
});
lowerGroup.orientation = "column";
lowerGroup.alignChildren = ["left", "center"];
lowerGroup.spacing = 10;
lowerGroup.margins = 0;
var upperRight = lowerGroup.add("radiobutton", undefined, undefined, {
name: "upperRight"
});
upperRight.text = "Upper Right";
upperRight.helpTip = "Radio buttons override the X & Y fields";
var middleRight = lowerGroup.add("radiobutton", undefined, undefined, {
name: "middleRight"
});
middleRight.text = "Middle Right";
middleRight.helpTip = "Radio buttons override the X & Y fields";
var lowerRight = lowerGroup.add("radiobutton", undefined, undefined, {
name: "lowerRight"
});
lowerRight.text = "Lower Right";
lowerRight.helpTip = "Radio buttons override the X & Y fields";
// XYGROUP
// =======
var xyGroup = dialogWindow.add("group", undefined, {
name: "xyGroup"
});
xyGroup.orientation = "row";
xyGroup.alignChildren = ["left", "center"];
xyGroup.spacing = 0;
xyGroup.margins = [0, 0, 0, 0];
xyGroup.alignment = ["left", "center"];
// XYPANEL
// =======
var xyPanel = xyGroup.add("panel", undefined, undefined, {
name: "xyPanel"
});
xyPanel.text = "X & Y Position";
xyPanel.orientation = "column";
xyPanel.alignChildren = ["left", "center"];
xyPanel.spacing = 5;
xyPanel.margins = [10, 10, 10, 10];
xyPanel.alignment = ["left", "center"];
var xValue = xyPanel.add('edittext {properties: {name: "xValue"}}');
xValue.helpTip = "Enter the X value";
xValue.preferredSize.width = 75;
xValue.text = "";
// Call the function to imit keyboard entry to digits
xyPanel.xValue.addEventListener('keydown', NumericEditKeyboardHandler);
////////////////////// peter kahrel scriptUI for dummies //////////////////////
// Preset the X field as active
xValue.active = true;
////////////////////// peter kahrel scriptUI for dummies //////////////////////
var yValue = xyPanel.add('edittext {properties: {name: "yValue"}}');
yValue.helpTip = "Enter the Y value";
yValue.preferredSize.width = 75;
yValue.text = "";
// Call the function to imit keyboard entry to digits
xyPanel.yValue.addEventListener('keydown', NumericEditKeyboardHandler);
////////////////////// peter kahrel scriptUI for dummies //////////////////////
// Make multiple groups act as one group
upperGroup.addEventListener("click", function () {
for (var i = 0; i < middleGroup.children.length; i++)
middleGroup.children[i].value = false;
});
upperGroup.addEventListener("click", function () {
for (var i = 0; i < lowerGroup.children.length; i++)
lowerGroup.children[i].value = false;
});
middleGroup.addEventListener("click", function () {
for (var i = 0; i < upperGroup.children.length; i++)
upperGroup.children[i].value = false;
});
middleGroup.addEventListener("click", function () {
for (var i = 0; i < lowerGroup.children.length; i++)
lowerGroup.children[i].value = false;
});
lowerGroup.addEventListener("click", function () {
for (var i = 0; i < middleGroup.children.length; i++)
middleGroup.children[i].value = false;
});
lowerGroup.addEventListener("click", function () {
for (var i = 0; i < upperGroup.children.length; i++)
upperGroup.children[i].value = false;
});
////////////////////// peter kahrel scriptUI for dummies //////////////////////
/////////////////////////////// joonas scriptUI ///////////////////////////////
// OKGROUP
// =======
var okGroup = dialogWindow.add("group", undefined, {
name: "okGroup"
});
okGroup.orientation = "column";
okGroup.alignChildren = ["left", "center"];
okGroup.spacing = 12;
okGroup.margins = [1, 1, 1, 1];
okGroup.alignment = ["left", "center"];
var okButton = okGroup.add("button", undefined, undefined, {
name: "okButton"
});
okButton.text = "OK";
var cancelButton = okGroup.add("button", undefined, undefined, {
name: "cancelButton"
});
cancelButton.text = "Cancel";
/////////////////////////////// joonas scriptUI ///////////////////////////////
////////////////////////////// tom_ruark @ adobe //////////////////////////////
/* https://feedback.photoshop.com/conversations/photoshop/photoshop-ability-to-ruler-origin-by-script/5f5f45bb4b561a3d425c7b32 */
// Version 2016.11.18
// Show how to get and set the ruler origin point for the current document
// Values are in pixels shifted 16 bits
// some constants to make it more readable
const classProperty = app.stringIDToTypeID("property");
const krulerOriginHStr = app.stringIDToTypeID("rulerOriginH");
const krulerOriginVStr = app.stringIDToTypeID("rulerOriginV");
const classDocument = app.stringIDToTypeID("document");
const typeOrdinal = app.stringIDToTypeID("ordinal");
const enumTarget = app.stringIDToTypeID("targetEnum");
const typeNULL = app.stringIDToTypeID("null");
const keyTo = app.stringIDToTypeID("to");
const eventSet = app.stringIDToTypeID("set");
// get the current values
GetRulerOrigin().toSource();
function GetRulerOrigin() {
var ro = {};
ro.horizontal = GetInfo(classDocument, krulerOriginHStr) >> 16;
ro.vertical = GetInfo(classDocument, krulerOriginVStr) >> 16;
return ro;
}
function SetRulerOrigin_Horiz(horiz) {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putProperty(classProperty, krulerOriginHStr);
ref.putEnumerated(classDocument, typeOrdinal, enumTarget);
desc.putReference(typeNULL, ref);
desc.putInteger(keyTo, horiz << 16);
executeAction(eventSet, desc, DialogModes.NO);
}
function SetRulerOrigin_Vert(vert) {
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putProperty(classProperty, krulerOriginVStr);
ref.putEnumerated(classDocument, typeOrdinal, enumTarget);
desc.putReference(typeNULL, ref);
desc.putInteger(keyTo, vert << 16);
executeAction(eventSet, desc, DialogModes.NO);
}
///////////////////////////////////////////////////////////////////////////////
// Function: GetInfo
// Usage: Get information from Photoshop
// Input: desiredClass, classApplication, classLayer, etc.
// desiredKey, optional specific key to get instead of everything
// this is recommended as all keys is an expensive call
// Return: ActionDescriptor or single value depending on what is asked for
///////////////////////////////////////////////////////////////////////////////
function GetInfo(desiredClass, desiredKey) {
var reference = new ActionReference();
if (typeof desiredKey != "undefined") {
reference.putProperty(stringIDToTypeID("property"), desiredKey);
}
reference.putEnumerated(desiredClass, stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
var desc = executeActionGet(reference);
if (typeof desiredKey != "undefined") {
return GetItemFromDescriptor(desc, desiredKey);
}
return desc;
}
///////////////////////////////////////////////////////////////////////////////
// Function: GetItemFromDescriptor
// Usage: Get a specific key from an ActionDescriptor
// Input: desc (ActionDescriptor), valid ActionDescriptor to pull info from
// desiredKey (Number), key in question, use charIDToTypeID() or
// stringIDToTypeID()
// Return: ActionDescriptor or single value depending on what is asked for
///////////////////////////////////////////////////////////////////////////////
function GetItemFromDescriptor(desc, desiredKey) {
if (desc.hasKey(desiredKey)) {
var typeID = desc.getType(desiredKey);
switch (typeID) {
case DescValueType.BOOLEANTYPE:
return desc.getBoolean(desiredKey);
break;
case DescValueType.STRINGTYPE:
return desc.getString(desiredKey);
break;
case DescValueType.DOUBLETYPE:
return desc.getDouble(desiredKey);
break;
case DescValueType.INTEGERTYPE:
return desc.getInteger(desiredKey);
break;
case DescValueType.LARGEINTEGERTYPE:
return desc.getLargeInteger(desiredKey);
break;
case DescValueType.OBJECTTYPE:
return desc.getObjectValue(desiredKey);
break;
case DescValueType.UNITDOUBLE:
var newT = desc.getUnitDoubleType(desiredKey);
var newV = desc.getUnitDoubleValue(desiredKey);
return new UnitValue(newV, newT);
break;
case DescValueType.ENUMERATEDTYPE:
return desc.getEnumerationValue(desiredKey);
break;
case DescValueType.CLASSTYPE:
return desc.getClass(desiredKey);
break;
case DescValueType.ALIASTYPE:
return desc.getPath(desiredKey);
break;
case DescValueType.RAWTYPE:
var tempStr = desc.getData(desiredKey);
var rawData = new Array();
for (var tempi = 0; tempi < tempStr.length; tempi++) {
rawData[tempi] = tempStr.charCodeAt(tempi);
}
return rawData;
break;
case DescValueType.REFERENCETYPE:
return desc.getReference(desiredKey);
break;
case DescValueType.LISTTYPE:
return desc.getList(desiredKey);
break;
default:
return;
}
}
return;
}
////////////////////////////// tom_ruark @ adobe //////////////////////////////
/////////////////////////////// joonas scriptUI ///////////////////////////////
okButton.onClick = function () {
dialogWindow.close();
/////////////////////////////// joonas scriptUI ///////////////////////////////
// Link function parameters to X & Y field values
if (xValue.text.length > 0) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(xValue.text);
}
if (yValue.text.length > 0) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Vert(yValue.text);
}
// Canvas variables
var rE = app.activeDocument.width; // rightEdge
var hC = app.activeDocument.width / 2; // horizontalCenter
var vC = app.activeDocument.height / 2; // verticalCenter
var bE = app.activeDocument.height; // bottomEdge
// Link function parameters to radio buttons
if (upperLeft.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
}
if (upperCenter.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(hC);
SetRulerOrigin_Vert(0);
}
if (upperRight.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(rE);
SetRulerOrigin_Vert(0);
}
if (middleLeft.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(vC);
}
if (middleCenter.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(hC);
SetRulerOrigin_Vert(vC);
}
if (middleRight.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(rE);
SetRulerOrigin_Vert(vC);
}
if (lowerLeft.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(bE);
}
if (lowerCenter.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(hC);
SetRulerOrigin_Vert(bE);
}
if (lowerRight.value === true) {
// Reset ruler origin to zero for a known start point
SetRulerOrigin_Horiz(0);
SetRulerOrigin_Vert(0);
// Set ruler origin to variables
SetRulerOrigin_Horiz(rE);
SetRulerOrigin_Vert(bE);
}
}
/////////////////////////////// joonas scriptUI ///////////////////////////////
// Execute window
dialogWindow.show();
/////////////////////////////// joonas scriptUI ///////////////////////////////
////////////////////////////// tom_ruark @ adobe //////////////////////////////
// Function to limit keyboard entry to digits
function NumericEditKeyboardHandler(event) {
try {
var keyIsOK = KeyIsNumeric(event) ||
KeyIsDelete(event) ||
KeyIsLRArrow(event) ||
KeyIsTabEnterEscape(event);
if (!keyIsOK) {
// Bad input: tell ScriptUI not to accept the keydown event
event.preventDefault();
/*
Notify user of invalid input: make sure NOT
to put up an alert dialog or do anything which
requires user interaction, because that
interferes with preventing the 'default'
action for the keydown event */
app.beep();
}
} catch (e) {
// alert ("Ack! bug in NumericEditKeyboardHandler: " + e);
}
}
function KeyHasModifier(event) {
return event.shiftKey || event.ctrlKey || event.altKey || event.metaKey;
}
function KeyIsNumeric(event) {
return (event.keyName >= '0') && (event.keyName <= '9') && !KeyHasModifier(event);
}
function KeyIsDelete(event) {
return (event.keyName == 'Backspace') && !(event.ctrlKey);
}
function KeyIsLRArrow(event) {
return ((event.keyName == 'Left') || (event.keyName == 'Right')) && !(event.altKey || event.metaKey);
}
function KeyIsTabEnterEscape(event) {
return event.keyName == 'Tab' || event.keyName == 'Enter' || event.keyName == 'Escape';
}
////////////////////////////// tom_ruark @ adobe //////////////////////////////
// Restore the ruler units
app.preferences.rulerUnits = savedRuler;
}
else {
alert('A document must be open to use this script!');
}
Copy link to clipboard
Copied
I was wondering: Stephen, do you also submit your scripts to the Adobe Exchange?
Copy link to clipboard
Copied
@PECourtejoie – The scripts are very organic, somebody has a problem or need and if I can help, I do so. Scripting is very much a hobby. I rarely set out with a plan of "I am going to create a specific script for publication".
Some scripts could be posted to the Exchange I guess.
Take for example the 1.3 version above with the GUI for changing the ruler origin point. It has a basic GUI, but the GUI needs more work for me to be truly happy with it. This work is beyond me.
I guess most of the scripts on this site are hidden "Easter eggs", there are thousands of valuable nuggets in the forum (and thousands lost in the forum changeover), if somebody is interested, they may find them, but they are possibly less visible than if posted in the Exchange.
Copy link to clipboard
Copied
Yes, it is the visibility and discoverability that I had in mind.
I suggested to Paul Riggott to create a Github of his creation, which he did.
Not sure about the legality of creating a community Github, listing all the scripts/Scriptlets shared here.
I know it would be quite an endeavour.
I'm afraid of the fact that we've not heard from him for far too long.