Mini Kabibi Habibi
#target photoshop-190
// (c) Copyright 2024. Adobe Systems, Incorporated. All rights reserved.
/*
@@@BUILDINFO@@@ photoshop_v2025.jsx 1.0.0 15-August-2024
*/
/*
@@@START_XML@@@
<?xml version="1.0" encoding="UTF-8"?>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en_US">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>This script enables other applications to communicate with Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="fr_FR">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Ce script permet à d'autres applications de communiquer avec Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="ja_JP">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>このスクリプトは、他のアプリケーションと Adobe Photoshop 2025 との通信を有効にします。</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="de_DE">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Mithilfe dieses Skripts können andere Anwendungen mit Adobe Photoshop 2025 kommunizieren.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="it_IT">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Questo script consente ad altre applicazioni di comunicare con Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="es_ES">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Este script posibilita que otras aplicaciones se comuniquen con Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="nl_NL">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Dit script laat andere toepassingen toe te communiceren met Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pt_BR">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Este script permite que outros aplicativos se comuniquem com o Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="nb_NO">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Skriptet gjør at andre programmer kan kommunisere med Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="da_DK">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Dette script betyder, at andre programmer kan kommunikere med Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="fi_FI">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Tämän komentosarjan avulla muut sovellukset ja Adobe Photoshop 2025 voivat kommunikoida keskenään.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="sv_SE">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Det här skriptet gör det möjligt för andra program att kommunicera med Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="zh_TW">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>此指令碼能讓其他應用程式與 Adobe Photoshop 2025 進行通訊。</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="zh_CN">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>此脚本使其它应用程序能够与 Adobe Photoshop 2025 进行通信。</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="ko_KR">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>이 스크립트를 사용하면 다른 응용 프로그램에서 Adobe Photoshop 2025과(와) 통신할 수 있습니다.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="ar_AE">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>يتيح هذا النص التنفيذي للتطبيقات الأخرى أن تتصل بـ Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="cs_CZ">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Tento skript umožňuje dalším aplikacím komunikovat s aplikací Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="el_GR">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Αυτή η δέσμη ενεργειών δίνει τη δυνατότητα σε άλλες εφαρμογές να επικοινωνούν με το Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="es_MX">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Este script posibilita que otras aplicaciones se comuniquen con Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="fr_CA">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Ce script permet à d'autres applications de communiquer avec Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="fr_XM">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Ce script permet à d'autres applications de communiquer avec Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="he_IL">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>סקריפט זה מאפשר ליישומים אחרים לתקשר עם Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="hu_HU">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Ez a parancsfájl gondoskodik arról, hogy más alkalmazások kommunikálhassanak az Adobe Photoshop 2025 programmal.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="pl_PL">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Ten skrypt umożliwia innym aplikacjom komunikowanie się z programem Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="ro_RO">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Acest script permite altor aplicaţii să comunice cu Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="ru_RU">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Этот сценарий позволяет другим приложениям обмениваться данными с Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="tr_TR">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Bu komut dosyası, diğer uygulamaların Adobe Photoshop 2025 ile iletişim kurmasını sağlar.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="uk_UA">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Цей сценарій забезпечує обмін даними між Adobe Photoshop 2025 та іншими програмами.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en_AE">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>This script enables other applications to communicate with Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="en_IL">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>This script enables other applications to communicate with Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
<ScriptInfo xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="fr_MA">
<dc:title>Adobe Photoshop 2025</dc:title>
<dc:description>Ce script permet à d'autres applications de communiquer avec Adobe Photoshop 2025.</dc:description>
</ScriptInfo>
@@@END_XML@@@
*/
// This JavaScript is to be read by Bridge, Photoshop, and other Adobe apps at
// launch. It enables some Photoshop-Bridge integration, such as installing
// the Photoshop automate commands in the Bridge menus, and generally exposes
// a larger Photoshop dom to the other apps.
// debug level: 0-2 (0:disable, 1:break on error, 2:break at beginning)
$.level = 0;
// debugger; // launch debugger on next line
// on localized builds we pull the $$$/Strings from a .dat file
$.localize = true;
//=================================================================
// Setup/Support
// This first portion of the script sets up an object to provide
// scope for all Photoshop BridgeTalk related routines to prevent
// name collision with other groups' scripts, defines some common
// utility functions, and adds some Photoshop related commands
// to the Bridge menus.
//=================================================================
try
{ // Overall try catch
//-----------------------------------------------------------------
// A Note About Exception Handling
//-----------------------------------------------------------------
// If execution of the body of a BridgeTalk message throws an
// exception, it will be silently swept under the carpet and not
// reported to the user. Therefore, many of the functions in here
// which are run as the body of a BridgeTalk message due to a user
// request have an overall try-catch to report such errors.
//
// Exceptions thrown out of Bridge MenuElement onSelect methods are
// also not reported, so they are wrapped in try-catch statements
// here.
//
// The X-DOM functions are not wrapped in try-catch statements so
// it is up to the caller to handle any exceptions if calling X-DOM
// functions via BridgeTalk.
//-----------------------------------------------------------------
// ================================================================
// ================================================================
// ================================================================
// Setup/Initialization
// The code below does basic initialization and setup tasks and
// must appear at the beggining of this script.
// ================================================================
// ================================================================
// ================================================================
try
{ // Inner try-catch to handle version info object disposal
var tempPSVersionInfo = new Object;
tempPSVersionInfo.scriptRevision = 19;
tempPSVersionInfo.btTargetName = 'photoshop'; // no version so BT can resolve to .032 or .064 as needed
tempPSVersionInfo.rootVersion = '190.0'; // no minor version so we can match against .032 or .064 as needed
tempPSVersionInfo.displayVersion = '2025'; // does not get localized
tempPSVersionInfo.bridgeTarget = 'bridge';
tempPSVersionInfo.bridgeMinimumRequiredTargetVersion = 14; // DO NOT CHANGE the version here - Photoshop supports Bridge 14 or newer
tempPSVersionInfo.bridgeDisplayVersion = '2025'; // does not get localized
tempPSVersionInfo.extensionManagerTargetVersion = '7';
tempPSVersionInfo.extensionManagerTarget = 'exman';
//-----------------------------------------------------------------
// Guard against loading in non-matching version of PS.
// This prevents the CC 2025 (and any future version) startup script
// from clobbering the CC startup script definitions on load (the
// original CC startup script did not have this check).
//-----------------------------------------------------------------
if ((BridgeTalk.appName == "photoshop") && (BridgeTalk.appVersion.indexOf (tempPSVersionInfo.rootVersion) != 0))
throw localize ("$$$/private/PSBI/Error/NotMatchingPSVersion=This script is not intended for this version of Photoshop. Skipping load.");
//-----------------------------------------------------------------
// Guard against loading script if matching version of PS is not
// installed.
//-----------------------------------------------------------------
// getTargets (0) returns all versions of all apps - see if this version is among them
// Include the root version to make sure we don't match other versions if run in an app that is not
// part of the group
if (BridgeTalk.getTargets (0).join ().indexOf (tempPSVersionInfo.btTargetName + '-' + tempPSVersionInfo.rootVersion) == -1)
{
if ((BridgeTalk.appName == "photoshop") && (BridgeTalk.appVersion.indexOf (tempPSVersionInfo.rootVersion) == 0))
{
// Something is wrong! BridgeTalk thinks this version of Photoshop is not installed, but it is running this script...
// Allow the script to load so that the user does not get bizarre JavaScript errors about photoshop not being defined,
// and can still Browse to Bridge from Photoshop if the Bridge installation is not damaged.
}
else
throw localize ("$$$/PSBI/Error/MatchingPSVersionNotInstalled=The version of Photoshop matching this script (%1) is not installed or its installation is damaged. Please reinstall.", tempPSVersionInfo.rootVersion);
}
//-----------------------------------------------------------------
// Guard against loading multiple revisions of the same startup
// script. The latest revision will take precedence.
//-----------------------------------------------------------------
if (typeof photoshop != "undefined")
{
if ((photoshop.versionInfo.scriptRevision == undefined) ||
(photoshop.versionInfo.scriptRevision < tempPSVersionInfo.scriptRevision))
{
// Delete the 'photoshop' object defined by the CC startup script; we will redefine it.
delete photoshop;
// if ((BridgeTalk.appName == "bridge") && (Number(BridgeTalk.appVersion.split(".")[0]) >= tempPSVersionInfo.bridgeMinimumRequiredTargetVersion))
// {
// // Remove all the menu items installed by the CC startup script; we will create new ones.
// MenuElement.remove ("PicturePackage");
// }
}
else
// Bail out right here.
throw localize ("$$$/PSBI/Error/PSObjectDefined=Object 'photoshop' has already been defined. Older revision ignored.");
}
}
catch (e)
{
delete tempPSVersionInfo;
throw e;
}
//-----------------------------------------------------------------
// Define photoshop object.
//-----------------------------------------------------------------
var photoshop = new Object;
photoshop.versionInfo = tempPSVersionInfo;
delete tempPSVersionInfo;
// Set the photoshop190 object equal to the generic photoshop object
// so photoshop190.foo() can be used.
photoshop190 = photoshop;
//-----------------------------------------------------------------
// Throughout this script commands are set up to be added to the
// Tools > Photoshop menu in Bridge. Since Bridge's menu API does
// not support automatic alphabetizing of menu items, we create
// an array with all the necessary menu item info in it, then sort
// it at the end of this script and create all the menu items.
//-----------------------------------------------------------------
photoshop.menuItemInfoArray = new Array ();
//-----------------------------------------------------------------
// An object used to control how UI is used and what behavior is
// chosen when checking to see if the correct version of PS is
// available to run a command.
//-----------------------------------------------------------------
AvailabilityCheckOptions.kBusyAsk = 0;
AvailabilityCheckOptions.kBusyWarn = 1;
AvailabilityCheckOptions.kBusyAutoQueue = 2;
AvailabilityCheckOptions.kBusyAutoCancel = 3;
function AvailabilityCheckOptions (inBusyAction, inWarnIfUnavailable)
{
// control how a busy PS is handled
this.busyAction = (inBusyAction == null) ? AvailabilityCheckOptions.kBusyAsk : inBusyAction;
this.warnBusyText = localize ("$$$/PSBI/Error/PSBusyWarn=Photoshop %1 is currently busy with another task. Please finish that task in Photoshop and try again.", photoshop.versionInfo.displayVersion);
this.askBusyText = localize ("$$$/PSBI/Error/PSBusyAsk=Photoshop %1 is currently busy with another task. Would you like to queue this command?", photoshop.versionInfo.displayVersion);
// control how an uninstalled version of PS is controlled
this.warnIfUnavailable = (inWarnIfUnavailable == null) ? true : inWarnIfUnavailable;
this.warnInsidePSText = localize ("$$$/PSBI/Error/OtherVersionRunningInPS=Photoshop %1 is required for this command. Please quit this version and try again.", photoshop.versionInfo.displayVersion);
// used to prevent UI from being shown twice in same call stack;
// this gets set and the return value is remembered
this.alreadyUsed = false;
this.alreadyUsedReturnValue = false;
}
// ================================================================
// ================================================================
// ================================================================
// CrossDOM/X-DOM
// Implements Photoshop's cross DOM API - the a small set of
// operations that are common to all Adobe apps.
// ================================================================
// ================================================================
// ================================================================
//-----------------------------------------------------------------
// executeScript (script) - Performs an "eval" on the given script.
//
// return value Object The value of evaling the last line
// of the script
// script String The script to be evaled
//-----------------------------------------------------------------
photoshop.executeScript = function (script, availabilityCheckOptions)
{
// Make sure this can be run.
if (availabilityCheckOptions == null)
availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
if (BridgeTalk.appName != "photoshop")
{
// Bring Photoshop to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
// Create a new BridgeTalk message for Photoshop to invoke
// executeScript.
var btMessage = new BridgeTalk;
btMessage.target = photoshop.versionInfo.btTargetName;
btMessage.body = "photoshop.executeScript (" + script.toSource () + ");";
btMessage.send();
}
else
{
app.bringToFront();
// This is Photoshop, so just call our DOM routine
eval (script.toString());
}
}
//-----------------------------------------------------------------
// open (files) - Performs the equivalent of File->Open on the
// requested paths. Accepts either an Array object or a single
// path.
//
// return value Array of File an array of all the
// successfully opened
// files
// files File or Array of File files to open
//-----------------------------------------------------------------
photoshop.open = function (files, availabilityCheckOptions)
{
// Make sure this can be run.
if (availabilityCheckOptions == null)
availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
if (BridgeTalk.appName != "photoshop")
{
// Bring Photoshop to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
// Create a new BridgeTalk message for Photoshop to invoke
// open.
var btMessage = new BridgeTalk;
btMessage.target = photoshop.versionInfo.btTargetName;
btMessage.body = "photoshop.open (" + files.toSource () + ");";
btMessage.send();
}
else
{
app.bringToFront();
// This is Photoshop, so just call our DOM routine with the files
var fileArray = photoshop.ExtractFileArray (files);
for (index = 0; index < fileArray.length; ++index)
{
var file = fileArray[index];
app.open (file);
}
}
}
//-----------------------------------------------------------------
// openAsNew ([creation-options]*) - Performs the equivalent of
// File->New. The creation-options are app-specific and should
// ideally map on to the app's new() function. PS has no creation
// options.
//
// return value Boolean true if successful
//-----------------------------------------------------------------
photoshop.openAsNew = function (availabilityCheckOptions)
{
// Make sure this can be run.
if (availabilityCheckOptions == null)
availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
if (BridgeTalk.appName != "photoshop")
{
// Bring Photoshop to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
// Create a new BridgeTalk message for Photoshop to invoke
// open.
var btMessage = new BridgeTalk;
btMessage.target = photoshop.versionInfo.btTargetName;
btMessage.body = "photoshop.openAsNew ();";
btMessage.send();
}
else
{
app.bringToFront();
// This is Photoshop, so just call our DOM routine
app.documents.add ();
}
}
//-----------------------------------------------------------------
// print (files) - Performs the equivalent of File->Print on the
// requested files.
//
// return value Array of File the array of files
// successfully
// printed
// files File or Array of File files to be printed
//-----------------------------------------------------------------
photoshop.print = function (files, availabilityCheckOptions)
{
// Make sure this can be run.
if (availabilityCheckOptions == null)
availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
if (BridgeTalk.appName != "photoshop")
{
// Bring Photoshop to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
// Create a new BridgeTalk message for Photoshop to invoke
// open.
var btMessage = new BridgeTalk;
btMessage.target = photoshop.versionInfo.btTargetName;
btMessage.body = "photoshop.print (" + files.toSource () + ");";
btMessage.send();
}
else
{
app.bringToFront();
// This is Photoshop, so just call our DOM routine with the files
var fileArray = photoshop.ExtractFileArray (files);
for (index = 0; index < fileArray.length; ++index)
{
var file = fileArray[index];
var document = app.open (file);
if (document != undefined)
{
var rememberDialogModes = displayDialogs;
displayDialogs = DialogModes.ALL;
document.print ();
displayDialogs = rememberDialogModes;
}
}
}
}
//-----------------------------------------------------------------
// quit () - Performs the equivalent of File->Exit or File->Close.
//
// return value undefined
//-----------------------------------------------------------------
photoshop.quit = function (availabilityCheckOptions)
{
// Make sure this can be run.
if (availabilityCheckOptions == null)
availabilityCheckOptions = new AvailabilityCheckOptions (AvailabilityCheckOptions.kBusyWarn, false); // warn if busy, don't warn if wrong version is running
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
if (BridgeTalk.appName != "photoshop")
{
// Bring Photoshop to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
// Create a new BridgeTalk message for Photoshop to invoke
// open.
var btMessage = new BridgeTalk;
btMessage.target = photoshop.versionInfo.btTargetName;
btMessage.body = "photoshop.quit ();";
btMessage.send();
}
else
{
app.bringToFront();
// This is Photoshop, so just call our DOM
var quitID = stringIDToTypeID ('quit');
executeAction (quitID, undefined, DialogModes.NO);
}
}
//-----------------------------------------------------------------
// reveal (file) - Gives the target app focus and brings the
// specified document to the foreground if it is already open.
//
// return value Boolean true if the file was open and was
// successfully brought to the
// foreground
// file File file to be revealed
//-----------------------------------------------------------------
photoshop.reveal = function (file, availabilityCheckOptions)
{
// Make sure this can be run.
if (availabilityCheckOptions == null)
availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
if (BridgeTalk.appName != "photoshop")
{
// Bring Photoshop to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
// Create a new BridgeTalk message for Photoshop to invoke
// open.
var btMessage = new BridgeTalk;
btMessage.target = photoshop.versionInfo.btTargetName;
btMessage.body = "photoshop.reveal (" + file.toSource () + ");";
btMessage.send();
}
else
{
app.bringToFront();
// This is Photoshop, so just call our DOM routine with the files
// Loop through the open documents looking for the one
// we want to reveal. If it is found, make it the active
// document.
var docNum = app.documents.length - 1;
while (docNum >= 0)
{
var document = app.documents[docNum];
// If document is a new unsaved document, accessing
// document.fullName results in an error. Comparing
// it to undefined also results in an error, so it
// is in a try-catch instead.
try
{
if (document.fullName.fsName == file.fsName)
{
app.activeDocument = document;
break;
}
}
catch (e)
{
// ignore.
}
--docNum;
}
}
}
// ================================================================
// ================================================================
// ================================================================
// Photoshop Commands
// The code below is for functionality which is present in
// Photoshop, such as Browse...
// ================================================================
// ================================================================
// ================================================================
//=================================================================
// Invoking Bridge
// Is called by Photoshop to invoke Bridge.
// Keep deprecated arguments for backwards compatibility with any
// scripts out in the wild.
//=================================================================
photoshop.invokeBridge = function (newWindow_deprecated, maximize_deprecated, path)
{
// Make sure this can be run, otherwise alert the user (true for UI).
if (!photoshop.correctBridgeIsAvailable (false))
return 0;
// We pass this down to ensure the message we create is based
// off of whether Bridge was running before we attempted to
// launch it, not after we attempted to launch it.
var wasRunning = false;
if (BridgeTalk.isRunning (photoshop.versionInfo.bridgeTarget))
{
wasRunning = true;
}
else
{
// Make sure we attempt to launch it explicitly. send() will
// typically do it, but can get confused and not do it under some
// circumstances, for example if BridgeTalk previously attempted
// to launch the target but the target never finished launching
// for whatever reason (maybe another copy is running on Windows).
BridgeTalk.launch (photoshop.versionInfo.bridgeTarget);
}
// Send an appropriate message to Bridge to tell it what to do.
var bt = photoshop.getInvokeBridgeMessage (path, wasRunning);
bt.send ();
return 1;
}
//=================================================================
// Invoking Extension Manager
// Is called by Photoshop to invoke Extension Manager.
//=================================================================
photoshop.invokeExtensionManager = function ()
{
// Make sure this can be run, otherwise, return 0
if (!photoshop.correctExtensionManagerIsAvailable() )
return 0;
// We pass this down to ensure the message we create is based
// off of whether Bridge was running before we attempted to
// launch it, not after we attempted to launch it.
var wasRunning = false;
if (BridgeTalk.isRunning (photoshop.versionInfo.extensionManagerTarget))
{
wasRunning = true;
}
else
{
// Make sure we attempt to launch it explicitly. send() will
// typically do it, but can get confused and not do it under some
// circumstances, for example if BridgeTalk previously attempted
// to launch the target but the target never finished launching
// for whatever reason (maybe another copy is running on Windows).
BridgeTalk.launch (photoshop.versionInfo.extensionManagerTarget);
}
return 1;
}
//=================================================================
// Launching Bridge
// Is called by Photoshop to launch Bridge in the background at
// startup.
//=================================================================
photoshop.launchBridgeInBackground = function ()
{
// Make sure this can be run, don't alert the user if it can't (false for no UI).
if (!photoshop.correctBridgeIsAvailable (false))
return;
if (!BridgeTalk.isRunning (photoshop.versionInfo.bridgeTarget))
{
BridgeTalk.launch (photoshop.versionInfo.bridgeTarget, 'background');
// On Mac we are able to effectively launch Bridge without Photoshop
// losing focus, so all we have to do is launch Bridge. On Windows we
// are not so lucky and must employ some trickery to avoid having
// Bridge take over as the active app.
if ($.os.charAt (0) == 'M')
return;
// Win trickery
// Get the version number of Bridge so we can locate its
// app/user specific startup directory.
var bridgeSpecifier = BridgeTalk.getSpecifier("bridge");
var bridgeVersion = null;
if (bridgeSpecifier != null)
bridgeVersion = Math.floor(Number(bridgeSpecifier.split("-")[1]));
// Define a function that will be run inside of Bridge to make
// Photoshop come to the foreground. This script will be
// written to a temporary startup script and will self-delete
// after run.
var launchBridgeBehindScript = function (bridgeVersion)
{
// On Windows, bringToFront is only effective if the calling app is
// the foreground app, so it can't be called until Bridge has created
// a window. So if necessary, we insert a handler function that
// deletes itself after one execution.
if (app.documents.length > 0)
{
// the document has already been created, so just bring PS to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
return;
}
// define the handler
var bringPSForwardOnceHandler = function (event)
{
// Run on document creation.
if (event.object.constructor.name == 'Document' && event.type == 'create')
{
// Bring Photoshop to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
// Remove this handler once it has run.
for (var index = 0; index < app.eventHandlers.length; index++)
{
if (app.eventHandlers[index] == this)
{
app.eventHandlers[index] = null;
break;
}
}
}
// Return false so Bridge will keep calling other event handlers.
return { handled: false };
}
// Install the event handler.
app.eventHandlers.push ({handler: bringPSForwardOnceHandler});
} // launchBridgeBehindScript
// Send the script defined above to Bridge for it to execute.
var bt = new BridgeTalk;
bt.target = photoshop.versionInfo.bridgeTarget;
bt.body = 'var func = ' + launchBridgeBehindScript.toString () + 'func ("' + bridgeVersion + '");';
bt.send ();
} // !BridgeTalk.isRunning (photoshop.versionInfo.bridgeTarget)
}
// ================================================================
// ================================================================
// ================================================================
// Bridge Commands
// The code below is for functionality which is present in Bridge,
// such as the automation commands and File > Place > In Photoshop.
// ================================================================
// ================================================================
// ================================================================
//=================================================================
// Place
// Sets up Place in Photoshop command in Bridge's Place menu.
//=================================================================
//-----------------------------------------------------------------
// Performs the equivalent of the File->Place
// command on the requested file.
//-----------------------------------------------------------------
photoshop.place = function (file, availabilityCheckOptions, linked)
{
try
{
// Make sure this can be run.
if (availabilityCheckOptions == null)
availabilityCheckOptions = new AvailabilityCheckOptions ();
// customize the behavior
availabilityCheckOptions.busyAction = AvailabilityCheckOptions.kBusyWarn;
availabilityCheckOptions.warnBusyText = localize ("$$$/PSBI/Error/PSBusyWarnPlace=Photoshop %1 is currently busy with another task. Please finish that task in Photoshop, open the document you want to place into, and try again.", photoshop.versionInfo.displayVersion);
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
if (BridgeTalk.appName != "photoshop")
{
// Bring Photoshop to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
// Create a new BridgeTalk message for Photoshop to invoke
// open.
var btMessage = new BridgeTalk;
btMessage.target = photoshop.versionInfo.btTargetName;
btMessage.body = "photoshop.place (" + file.toSource () + "," + availabilityCheckOptions.toSource () + "," + linked + ");";
btMessage.send();
}
else
{
app.bringToFront();
var fileArray = photoshop.ExtractFileArray (file);
// This is Photoshop, so just call our DOM routine with the files
if (app.documents.length > 0)
{
if (fileArray.length > 0)
{
var theFile = fileArray[0];
// Set up generic placement information.
var offsetID = stringIDToTypeID ('offset');
var horizID = stringIDToTypeID ('horizontal');
var vertID = stringIDToTypeID ('vertical');
var distUnitID = stringIDToTypeID ('distanceUnit');
var offsetDesc = new ActionDescriptor ();
offsetDesc.putUnitDouble (horizID, distUnitID, 0.000000);
offsetDesc.putUnitDouble (vertID, distUnitID, 0.000000);
var nullID = charIDToTypeID ('null');
var ftcenterID = stringIDToTypeID ('freeTransformCenterState');
var quadCenterID = stringIDToTypeID ('quadCenterState');
var avgID = stringIDToTypeID ('QCSAverage');
var placeInfoDesc = new ActionDescriptor ();
placeInfoDesc.putEnumerated (ftcenterID, quadCenterID, avgID);
placeInfoDesc.putObject (offsetID, offsetID, offsetDesc);
// Set up the file.
placeInfoDesc.putPath (nullID, theFile);
// Suppress choose file dialog.
var overrideOpenID = stringIDToTypeID ('overrideOpen');
placeInfoDesc.putBoolean (overrideOpenID, true);
// Force it to record.
var forceRecordKey = stringIDToTypeID ('forceRecording');
placeInfoDesc.putBoolean (forceRecordKey, true);
// Add whether it's linked or embedded. It's a newer parameter, so handle
// it being undefined.
if (linked != undefined)
{
var linkedKey = stringIDToTypeID ('linked');
placeInfoDesc.putBoolean (linkedKey, linked);
}
// Do the Place.
var placeID = stringIDToTypeID ('placeEvent');
executeAction (placeID, placeInfoDesc, DialogModes.ALL);
// force deletion of ActionDescriptor now
offsetDesc = null;
placeInfoDesc = null;
$.gc();
}
if (fileArray.length > 1)
alert (localize ("$$$/PSBI/Place/OnlyFirstFile=Only the first file was placed."));
}
else
{
for (index = 0; index < fileArray.length; ++index)
{
var file = fileArray[index];
// Open as a Smart Object
app.open (file, undefined, true);
}
}
}
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//=================================================================
// saveActiveDocumentAsPSBOnDemand
// Utility function to allow saving in psb file format when necessary
//=================================================================
photoshop.saveActiveDocumentAsPSBOnDemand = function( destPath )
{
var startRulerUnits = app.preferences.rulerUnits;
try
{
var doc = app.activeDocument;
app.preferences.rulerUnits = Units.PIXELS;
if (doc.height.value > 30000 || doc.width.value > 30000)
{
const eventSave = app.charIDToTypeID('save');
const keyAs = app.charIDToTypeID('As ');
const keyIn = app.charIDToTypeID('In ');
const klargeDocumentFormatStr = app.charIDToTypeID('Pht8'); // NOT defined in PITerminology.h
app.preferences.rulerUnits = startRulerUnits;
var desc = new ActionDescriptor();
var bigDesc = new ActionDescriptor();
desc.putObject( keyAs, klargeDocumentFormatStr, bigDesc );
desc.putPath( keyIn, new File( destPath ) );
executeAction( eventSave, desc, DialogModes.NO );
}
else
{
app.preferences.rulerUnits = startRulerUnits;
doc.saveAs( File( destPath ) );
}
}
catch (error)
{
app.preferences.rulerUnits = startRulerUnits;
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//=================================================================
// Photomerge
// Sets up Photoshop's Photomerge automation command to be
// accessed from the Bridge.
//=================================================================
// This is like the version below, but does not open any dialogs.
// It's used for the autoCollections feature in Bridge.
photoshop.noDialogPhotomerge = function( files )
{
try
{
if (BridgeTalk.appName != "photoshop")
{
// Bring Photoshop to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
// Create a new BridgeTalk message for Photoshop to invoke
// Photomerge with the selected files
var btMessage = new BridgeTalk;
btMessage.target = photoshop.versionInfo.btTargetName;
btMessage.body = "photoshop.noDialogPhotomerge (" + files.toSource () + ");";
btMessage.send ();
}
else
{
var destPath = files.splice(0,1);
var gFilesFromBridge = files;
var strPresets = localize ("$$$/ApplicationPresetsFolder/Presets=Presets");
var strScripts = localize ("$$$/PSBI/Automate/ImageProcessor/Photoshop/Scripts=Scripts");
var strPhotomerge = localize ("$$$/PSBI/Automate/Photomerge/Photoshop/FileName=Photomerge.jsx");
var ipFilePath = app.path + "/" + strPresets + "/" + strScripts + "/" + strPhotomerge;
var ipFile = new File (ipFilePath);
var rememberDialogModes = displayDialogs;
displayDialogs = DialogModes.NO;
if (ipFile.exists)
{
runphotomergeFromScript = true;
$.evalFile( ipFilePath );
photomerge.createPanorama( files );
photoshop.saveActiveDocumentAsPSBOnDemand(destPath);
app.activeDocument.close();
runphotomergeFromScript = false;
}
else
alert (localize ("$$$/PSBI/Automate/Photomerge/NotFound=%1 could not be found.", strPhotomerge));
displayDialogs = rememberDialogModes;
}
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//-----------------------------------------------------------------
// This routine takes an array of files. If called by Photoshop,
// it will invoke Photomerge with the files. If called by
// any other app, it will send a BridgeTalk message to Photoshop
// to invoke this routine with the same arguments.
//-----------------------------------------------------------------
photoshop.photomerge = function (/* Array */ files, availabilityCheckOptions)
{
try
{
// Make sure this can be run.
if (availabilityCheckOptions == null)
availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
if (BridgeTalk.appName != "photoshop")
{
// Bring Photoshop to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
// Create a new BridgeTalk message for Photoshop to invoke
// Photomerge with the selected files
var btMessage = new BridgeTalk;
btMessage.target = photoshop.versionInfo.btTargetName;
btMessage.body = "photoshop.photomerge (" + files.toSource () + ");";
btMessage.send ();
}
else
{
app.bringToFront();
var gFilesFromBridge = files;
var strPresets = localize ("$$$/ApplicationPresetsFolder/Presets=Presets");
var strScripts = localize ("$$$/PSBI/Automate/ImageProcessor/Photoshop/Scripts=Scripts");
var strPhotomerge = localize ("$$$/PSBI/Automate/Photomerge/Photoshop/FileName=Photomerge.jsx");
var ipFilePath = app.path + "/" + strPresets + "/" + strScripts + "/" + strPhotomerge;
var ipFile = new File (ipFilePath);
var rememberDialogModes = displayDialogs;
displayDialogs = DialogModes.ALL;
if (ipFile.exists)
{
$.evalFile( ipFilePath );
}
else
alert (localize ("$$$/PSBI/Automate/Photomerge/NotFound=%1 could not be found.", strPhotomerge));
displayDialogs = rememberDialogModes;
}
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//-----------------------------------------------------------------
// This routine is called when the Bridge's Photomerge menu item is
// chosen.
//-----------------------------------------------------------------
photoshop.photomergeFromBridge = function ()
{
try
{
// Make sure this can be run.
var availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
var files = photoshop.getBridgeFileListForAutomateCommand (true, true);
if (files.length != 0)
photoshop.photomerge (files, availabilityCheckOptions);
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//=================================================================
// Contact Sheet
// Sets up Photoshop's Contact Sheet automation command to be
// accessed from the Bridge.
//=================================================================
//-----------------------------------------------------------------
// This routine takes an array of files. If called by Photoshop,
// it will invoke Contact Sheet with the files. If called by
// any other app, it will send a BridgeTalk message to Photoshop
// to invoke this routine with the same arguments.
//-----------------------------------------------------------------
photoshop.contactSheet = function (/* Array */ files, availabilityCheckOptions)
{
try
{
// Make sure this can be run.
if (availabilityCheckOptions == null)
availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
if (BridgeTalk.appName != "photoshop")
{
// Bring Photoshop to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
// Create a new BridgeTalk message for Photoshop to invoke
// Contact Sheet with the selected files
var btMessage = new BridgeTalk;
btMessage.target = photoshop.versionInfo.btTargetName;
btMessage.body = "photoshop.contactSheet (" + files.toSource () + ");";
btMessage.send ();
}
else
{
app.bringToFront();
photoshop.runActionCommand ('0B71D221-F8CE-11d2-B21B-0008C75B322C', files);
}
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//-----------------------------------------------------------------
// This routine is called when the Bridge's Contact Sheet menu item
// is chosen.
//-----------------------------------------------------------------
photoshop.contactSheetFromBridge = function ()
{
try
{
// Make sure this can be run.
var availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
var files = photoshop.getBridgeFileListForAutomateCommand (true, false);
if (files.length != 0)
photoshop.contactSheet (files, availabilityCheckOptions);
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//=================================================================
// Picture Package
// Sets up Photoshop's Picture Package automation command to be
// accessed from the Bridge.
//=================================================================
//-----------------------------------------------------------------
// This routine takes an array of files. If called by Photoshop,
// it will invoke Picture Package with the files. If called by
// any other app, it will send a BridgeTalk message to Photoshop
// to invoke this routine with the same arguments.
//-----------------------------------------------------------------
photoshop.picturePackage = function (/* Array */ files, availabilityCheckOptions)
{
try
{
// Make sure this can be run.
if (availabilityCheckOptions == null)
availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
if (BridgeTalk.appName != "photoshop")
{
// Bring Photoshop to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
// Create a new BridgeTalk message for Photoshop to invoke
// Picture Package with the selected files
var btMessage = new BridgeTalk;
btMessage.target = photoshop.versionInfo.btTargetName;
btMessage.body = "photoshop.picturePackage (" + files.toSource () + ");";
btMessage.send ();
}
else
{
app.bringToFront();
photoshop.runActionCommand ('4C1ABF40-DD82-11d2-B20F-0008C75B322C', files);
}
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//-----------------------------------------------------------------
// This routine is called when the Bridge's Picture Package menu
// item is chosen.
//-----------------------------------------------------------------
photoshop.picturePackageFromBridge = function ()
{
try
{
// Make sure this can be run.
var availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
var files = photoshop.getBridgeFileListForAutomateCommand (true, false);
if (files.length != 0)
photoshop.picturePackage (files, availabilityCheckOptions);
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//-----------------------------------------------------------------
// The code below inserts the PicturePackage menu item into the
// Bridge menus. It requires the optional Photoshop WebContactSheetII
// plug-in to be manually installed by the user. Uncomment the following
// Bridge menu insertion code if you want to invoke such functionality
// directly from Bridge.
//-----------------------------------------------------------------
/* -------------------------- START -------------------------------
if ((BridgeTalk.appName == "bridge") && (Number(BridgeTalk.appVersion.split(".")[0]) >= photoshop.versionInfo.bridgeMinimumRequiredTargetVersion))
{
// Use temp function to keep vars out of global namespace.
photoshop.tempFunction = function ()
{
// Set up the info necessary for inserting this item into the Bridge's menus later.
var menuItemInfo = new Object;
menuItemInfo.text = localize ("$$$/PSBI/Menu/Automate/PicturePackage=Picture Package...");
menuItemInfo.name = 'PicturePackage';
menuItemInfo.onSelect = photoshop.picturePackageFromBridge;
photoshop.menuItemInfoArray.push (menuItemInfo);
}
photoshop.tempFunction ();
delete photoshop.tempFunction;
}
----------------------------- END -------------------------------*/
//=================================================================
// Batch
// Sets up Photoshop's Batch automation command to be
// accessed from the Bridge.
//=================================================================
//-----------------------------------------------------------------
// This routine takes an array of files. If called by Photoshop,
// it will invoke Batch with the files. If called by
// any other app, it will send a BridgeTalk message to Photoshop
// to invoke this routine with the same arguments.
//-----------------------------------------------------------------
photoshop.batch = function (/* Array */ files, availabilityCheckOptions)
{
try
{
if (availabilityCheckOptions == null)
availabilityCheckOptions = new AvailabilityCheckOptions ();
// Make sure this can be run.
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
if (BridgeTalk.appName != "photoshop")
{
// Bring Photoshop to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
// Create a new BridgeTalk message for Photoshop to invoke
// Batch with the selected files
var btMessage = new BridgeTalk;
btMessage.target = photoshop.versionInfo.btTargetName;
btMessage.body = "photoshop.batch (" + files.toSource () + ");";
btMessage.send ();
}
else
{
app.bringToFront();
photoshop.runActionCommand ('batch', files,
localize ("$$$/PSBI/Automate/BatchSettingsFile=Batch via Bridge Settings"));
}
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//-----------------------------------------------------------------
// This routine is called when the Bridge's Batch menu item is
// chosen.
//-----------------------------------------------------------------
photoshop.batchFromBridge = function ()
{
try
{
var availabilityCheckOptions = new AvailabilityCheckOptions ();
// Make sure this can be run.
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
var files = photoshop.getBridgeFileListForAutomateCommand (true, false);
if (files.length != 0)
photoshop.batch (files, availabilityCheckOptions);
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//-----------------------------------------------------------------
// This routine takes an array of files. If called by Photoshop,
// it will invoke Load Files into Stacks script with the files. If called by
// any other app, it will send a BridgeTalk message to Photoshop
// to invoke this routine with the same arguments.
//-----------------------------------------------------------------
photoshop.loadFilesIntoStack = function (files, availabilityCheckOptions)
{
try
{
// Make sure this can be run.
if (availabilityCheckOptions == null)
availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
if (BridgeTalk.appName != "photoshop")
{
// Bring Photoshop to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
// Create a new BridgeTalk message for Photoshop to invoke
// LoadFilesIntoStack with the selected files
var btMessage = new BridgeTalk;
btMessage.target = photoshop.versionInfo.btTargetName;
btMessage.body = "photoshop.loadFilesIntoStack (" + files.toSource () + ");";
btMessage.send ();
}
else
{
app.bringToFront();
// Load Files into Stack script will recognize this and use it
var gFilesFromBridge = files;
var strPresets = localize ("$$$/ApplicationPresetsFolder/Presets=Presets");
var strScripts = localize ("$$$/PSBI/Automate/ImageProcessor/Photoshop/Scripts=Scripts");
var strFile2Stack = "Load Files into Stack.jsx";
var ipFilePath = app.path + "/" + strPresets + "/" + strScripts + "/" + strFile2Stack;
var ipFile = new File (ipFilePath);
var rememberDialogModes = displayDialogs;
displayDialogs = DialogModes.ALL;
if (ipFile.exists)
{
$.evalFile( ipFilePath );
// alert (localize ("$$$/PSBI/Automate/LoadFiles2Stack/CouldNotOpen=%1 could not be opened.", strFile2Stack));
}
else
alert (localize ("$$$/PSBI/Automate/LoadFiles2Stack/NotFound=%1 could not be found.", strFile2Stack));
displayDialogs = rememberDialogModes;
}
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//-----------------------------------------------------------------
// This routine is called when the Bridge's loadFilesIntoStack menu
// item is chosen.
//-----------------------------------------------------------------
photoshop.loadFilesIntoStackFromBridge = function ()
{
try
{
// Make sure this can be run.
var availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
var files = photoshop.getBridgeFileListForAutomateCommand (true, false);
if (files.length != 0)
photoshop.loadFilesIntoStack (files, availabilityCheckOptions);
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//=================================================================
// LensCorrect
// Sets up Photoshop's LensCorrect JavaScript to be
// accessed from the Bridge.
//=================================================================
//-----------------------------------------------------------------
// This routine takes an array of files. If called by Photoshop,
// it will invoke Lens Correct with the files. If called by
// any other app, it will send a BridgeTalk message to Photoshop
// to invoke this routine with the same arguments.
//-----------------------------------------------------------------
photoshop.lensCorrect = function (files, availabilityCheckOptions)
{
try
{
// Make sure this can be run.
if (availabilityCheckOptions == null)
availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
if (BridgeTalk.appName != "photoshop")
{
// Bring Photoshop to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
// Create a new BridgeTalk message for Photoshop to invoke
// MergeToHDR with the selected files
var btMessage = new BridgeTalk;
btMessage.target = photoshop.versionInfo.btTargetName;
btMessage.body = "photoshop.lensCorrect (" + files.toSource () + ");";
btMessage.send ();
}
else
{
app.bringToFront();
// Lens Correction script will recognize this and use it
var gFilesFromBridge = files;
var strPresets = localize ("$$$/ApplicationPresetsFolder/Presets=Presets");
var strScripts = localize ("$$$/PSBI/Automate/ImageProcessor/Photoshop/Scripts=Scripts");
var strLensCorrect = localize ("$$$/private/PSBI/Automate/LensCorrect/Photoshop/FileName=Lens Correct.jsx");
var ipFilePath = app.path + "/" + strPresets + "/" + strScripts + "/" + strLensCorrect;
var ipFile = new File (ipFilePath);
var rememberDialogModes = displayDialogs;
displayDialogs = DialogModes.ALL;
if (ipFile.exists)
{
$.evalFile( ipFilePath );
// alert (localize ("$$$/PSBI/Automate/MergeToHDR/CouldNotOpen=%1 could not be opened.", strMerge2HDR));
}
else
alert (localize ("$$$/PSBI/Automate/MergeToHDR/NotFound=%1 could not be found.", strLensCorrect));
displayDialogs = rememberDialogModes;
}
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//-----------------------------------------------------------------
// This routine is called when the Bridge's lensCorrect menu
// item is chosen.
//-----------------------------------------------------------------
photoshop.lensCorrectFromBridge = function ()
{
try
{
// Make sure this can be run.
var availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
var files = photoshop.getBridgeFileListForAutomateCommand (true, false);
if (files.length != 0)
photoshop.lensCorrect (files, availabilityCheckOptions);
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//=================================================================
// MergeToHDR
// Sets up Photoshop's MergeToHDR JavaScript to be
// accessed from the Bridge.
//=================================================================
// This is like the version below, but does not open any dialogs
// in Photoshop. Used by the autocollections feature in Bridge.
photoshop.noDialogMergeToHDR = function( files )
{
try
{
if (BridgeTalk.appName != "photoshop")
{
// Bring Photoshop to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
// Create a new BridgeTalk message for Photoshop to invoke
// MergeToHDR with the selected files
var btMessage = new BridgeTalk;
btMessage.target = photoshop.versionInfo.btTargetName;
btMessage.body = "photoshop.noDialogMergeToHDR (" + files.toSource () + ");";
btMessage.send ();
}
else
{
// Take the first as the destination
var destPath = files.splice(0,1);
// Merge to HDR script will recognize this and use it
var gFilesFromBridge = files;
var strPresets = localize ("$$$/ApplicationPresetsFolder/Presets=Presets");
var strScripts = localize ("$$$/PSBI/Automate/ImageProcessor/Photoshop/Scripts=Scripts");
var strMerge2HDR = localize ("$$$/PSBI/Automate/MergeToHDR/Photoshop/FileName=Merge To HDR.jsx");
var ipFilePath = app.path + "/" + strPresets + "/" + strScripts + "/" + strMerge2HDR;
var ipFile = new File (ipFilePath);
var rememberDialogModes = displayDialogs;
displayDialogs = DialogModes.NO; //???
if (ipFile.exists)
{
runMergeToHDRFromScript = true;
$.evalFile( ipFilePath );
mergeToHDR.mergeFilesToHDR( files, true );
photoshop.saveActiveDocumentAsPSBOnDemand(destPath);
app.activeDocument.close( );
// alert (localize ("$$$/PSBI/Automate/MergeToHDR/CouldNotOpen=%1 could not be opened.", strMerge2HDR));
runMergeToHDRFromScript = false;
}
else
alert (localize ("$$$/PSBI/Automate/MergeToHDR/NotFound=%1 could not be found.", strMerge2HDR));
displayDialogs = rememberDialogModes;
}
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//-----------------------------------------------------------------
// This routine takes an array of files. If called by Photoshop,
// it will invoke MergeToHDR with the files. If called by
// any other app, it will send a BridgeTalk message to Photoshop
// to invoke this routine with the same arguments.
//-----------------------------------------------------------------
photoshop.mergeToHDR = function (files, availabilityCheckOptions)
{
try
{
// Make sure this can be run.
if (availabilityCheckOptions == null)
availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
if (BridgeTalk.appName != "photoshop")
{
// Bring Photoshop to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
// Create a new BridgeTalk message for Photoshop to invoke
// MergeToHDR with the selected files
var btMessage = new BridgeTalk;
btMessage.target = photoshop.versionInfo.btTargetName;
btMessage.body = "photoshop.mergeToHDR (" + files.toSource () + ");";
btMessage.send ();
}
else
{
app.bringToFront();
// Merge to HDR script will recognize this and use it
var gFilesFromBridge = files;
var strPresets = localize ("$$$/ApplicationPresetsFolder/Presets=Presets");
var strScripts = localize ("$$$/PSBI/Automate/ImageProcessor/Photoshop/Scripts=Scripts");
var strMerge2HDR = localize ("$$$/PSBI/Automate/MergeToHDR/Photoshop/FileName=Merge To HDR.jsx");
var ipFilePath = app.path + "/" + strPresets + "/" + strScripts + "/" + strMerge2HDR;
var ipFile = new File (ipFilePath);
var rememberDialogModes = displayDialogs;
displayDialogs = DialogModes.ALL;
if (ipFile.exists)
{
$.evalFile( ipFilePath );
// alert (localize ("$$$/PSBI/Automate/MergeToHDR/CouldNotOpen=%1 could not be opened.", strMerge2HDR));
}
else
alert (localize ("$$$/PSBI/Automate/MergeToHDR/NotFound=%1 could not be found.", strMerge2HDR));
displayDialogs = rememberDialogModes;
}
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//-----------------------------------------------------------------
// This routine is called when the Bridge's mergeToHDR menu
// item is chosen.
//-----------------------------------------------------------------
photoshop.mergeToHDRFromBridge = function ()
{
try
{
// Make sure this can be run.
var availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
var files = photoshop.getBridgeFileListForAutomateCommand (true, false);
if (files.length != 0)
photoshop.mergeToHDR (files, availabilityCheckOptions);
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//=================================================================
// ImageProcessor
// Sets up Photoshop's Image Processor JavaScript to be
// accessed from the Bridge.
//=================================================================
//-----------------------------------------------------------------
// This routine takes an array of files. If called by Photoshop,
// it will invoke Image Processor with the files. If called by
// any other app, it will send a BridgeTalk message to Photoshop
// to invoke this routine with the same arguments.
//-----------------------------------------------------------------
photoshop.imageprocessor = function (files, availabilityCheckOptions)
{
try
{
// Make sure this can be run.
if (availabilityCheckOptions == null)
availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
if (BridgeTalk.appName != "photoshop")
{
// Bring Photoshop to the foreground.
BridgeTalk.bringToFront (photoshop.versionInfo.btTargetName);
// Create a new BridgeTalk message for Photoshop to invoke
// Image Processor with the selected files
var btMessage = new BridgeTalk;
btMessage.target = photoshop.versionInfo.btTargetName;
btMessage.body = "photoshop.imageprocessor (" + files.toSource () + ");";
btMessage.send ();
}
else
{
app.bringToFront();
// Image Processor script will recognize this and use it
var gFilesFromBridge = files;
var strPresets = localize ("$$$/ApplicationPresetsFolder/Presets=Presets");
var strScripts = localize ("$$$/PSBI/Automate/ImageProcessor/Photoshop/Scripts=Scripts");
var strImageProcessor = localize ("$$$/PSBI/Automate/ImageProcessor/Photoshop/FileName=Image Processor.jsx");
var ipFile = new File (app.path + "/" + strPresets + "/" + strScripts + "/" + strImageProcessor);
var rememberDialogModes = displayDialogs;
displayDialogs = DialogModes.ALL;
if (ipFile.exists)
{
if (ipFile.open ('r'))
{
var script = ipFile.read ();
ipFile.close ();
eval (script);
}
else
alert (localize ("$$$/PSBI/Automate/ImageProcessor/CouldNotOpen=Image Processor.jsx could not be opened."));
}
else
alert (localize ("$$$/PSBI/Automate/ImageProcessor/NotFound=Image Processor.jsx could not be found."));
displayDialogs = rememberDialogModes;
}
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//-----------------------------------------------------------------
// This routine is called when the Bridge's Image Processor menu
// item is chosen.
//-----------------------------------------------------------------
photoshop.imageprocessorFromBridge = function ()
{
try
{
// Make sure this can be run.
var availabilityCheckOptions = new AvailabilityCheckOptions ();
if (!photoshop.correctPSIsAvailable (availabilityCheckOptions))
return;
var files = photoshop.getBridgeFileListForAutomateCommand (true, false);
if (files.length != 0)
photoshop.imageprocessor (files, availabilityCheckOptions);
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//=================================================================
// Setup Tools > Photoshop menu in Bridge.
// Creates the menu, then sorts all the menu items we want to
// create before actually adding them to the menu.
//=================================================================
if ((BridgeTalk.appName == "bridge") && (Number(BridgeTalk.appVersion.split(".")[0]) >= photoshop.versionInfo.bridgeMinimumRequiredTargetVersion))
{
// Use temp function to keep vars out of global namespace.
photoshop.tempFunction = function ()
{
// The 'Photoshop Services' menu is installed by OLS, the 'Photoshop' menu
// in installed either by this script, or by the Workflow Automation Scripts
// (AdobeLibrary1.jsx) which also install menus for other apps. To get the
// menus in the correct order, all three scripts cooperate - so make sure
// you are aware of what's happening before changing this code.
var psServicesMenuExists = MenuElement.find ('Tools/PhotoshopServices') != null;
// Add a new Photoshop submenu in the Bridge's Tools menu.
var photoshopSubMenu = MenuElement.create ( "menu",
localize ("$$$/PhotoshopJSX/Menu/Photoshop=Photoshop"),
psServicesMenuExists ? "after Tools/PhotoshopServices" : 'after submenu/VersionCue',
'tools/ps');
// Define a function that will sort the menu items for us.
function menuTextOrder (a, b)
{
// Pass 'a' into 'b' to get reverse sort order so that they can be
// added at the top of the menu and still be in alphabetical order
// (the WAS scripts install additional menu items that end up below
// these).
return b.text.toLocaleLowerCase ().localeCompare (a.text.toLocaleLowerCase ());
}
// Sort the menu items
photoshop.menuItemInfoArray.sort (menuTextOrder);
// Add the menu items to the Photoshop menu.
for (var index = 0; index < photoshop.menuItemInfoArray.length; index++)
{
var menuItemInfo = photoshop.menuItemInfoArray[index];
var menuItem = MenuElement.create ( 'command',
menuItemInfo.text,
'at the beginning of tools/ps',
menuItemInfo.name,
photoshop.versionInfo.btTargetName);
menuItem.onSelect = menuItemInfo.onSelect;
}
// delete photoshop.menuItemInfoArray; keep this around so we can add Optional plug-ins later
}
photoshop.tempFunction ();
delete photoshop.tempFunction;
}
//-----------------------------------------------------------------
// Opens 'file' using provided ACR descriptor and dialogMode,
// if non-null. Provides lightroom doc id, BridgeTalk id, and save
// descriptor to the app so that it can track them. saveDesc is
// used to specify the save location, format, and options when
// the file is saved, and the lightroom doc id and BridgeTalk id
// are used to notify Lightroom when the file is saved or closed
// (see notifyLightroomDocSaved and notifyLightroomDocClosed).
//-----------------------------------------------------------------
photoshop.openFromLightroom = function (file, // required. file to open
acrDesc, // optional. pass acr descriptor to have PS open file with custom ACR settings
lightroomDocID, // optional. include for notifications on save and close
bridgeTalkID, // required if lightroomDocID is present. Pass sending app's BT id
saveDesc, // optional. pass save desc to have PS use provided format, location, etc for save
dialogMode) // optional. defaults to DisplayDialogs.ERROR. used by M2HDR and Photomerge scripts
{
var result = false;
// use ERROR dialog mode unless otherwise requested. This will show things like
// color profile mismatch and missing font dialogs,
if (dialogMode == null)
dialogMode = DialogModes.ERROR;
try
{
// construct an open descriptor with all of the info provided
var openDesc = new ActionDescriptor();
// add the file to open
openDesc.putPath (stringIDToTypeID ("target"), file);
// force the open to be recorded if recording is on
openDesc.putBoolean (stringIDToTypeID ("forceRecording"), true);
// Use ACR open parameters descriptor if provided
if (acrDesc != null)
{
openDesc.putObject (stringIDToTypeID("as"), stringIDToTypeID("Adobe Camera Raw"), acrDesc);
}
// include the info needed for PS to track the file and notify LR on save and/or close
if ((lightroomDocID != null) && (bridgeTalkID != null))
{
openDesc.putString (stringIDToTypeID ("lightroomDocID"), lightroomDocID);
openDesc.putString (stringIDToTypeID ("lightroomBridgetalkID"), bridgeTalkID);
}
// Use save desriptor if provided. At minimum, should include 'as' (format) and
// 'in' (save location) entries as well as any sub-entries to the format object
// that are required to keep the options dialog from showing for the format.
if (saveDesc != null)
{
openDesc.putObject (stringIDToTypeID ('lightroomSaveParams'), stringIDToTypeID ('save'), saveDesc);
}
// open the file and return the result (Photomerge and Merge To HDR need the value)
result = app.executeAction (stringIDToTypeID( "open" ), openDesc, dialogMode);
}
catch (error)
{
if (dialogMode != DialogModes.NO)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
return result;
}
//-----------------------------------------------------------------
// Runs Merge to HDR script, providing it with all the parameters
// to this method. Merge to HDR uses them when opening files,
// by invoking openFromLightroom(). See that method for argument
// descriptions.
//-----------------------------------------------------------------
photoshop.mergeToHDRFromLightroom = function ( files,
acrDescs,
lightroomDocID,
bridgeTalkID,
saveDesc)
{
try
{
// Merge to HDR script will recognize these and use them
var gFilesFromLightroom = files;
var gOpenParamsFromLightroom = acrDescs;
var gLightroomDocID = lightroomDocID;
var gBridgeTalkID = bridgeTalkID;
var gLightroomSaveParams = saveDesc;
var strPresets = localize ("$$$/ApplicationPresetsFolder/Presets=Presets");
var strScripts = localize ("$$$/PSBI/Automate/ImageProcessor/Photoshop/Scripts=Scripts");
var strMerge2HDR = localize ("$$$/PSBI/Automate/MergeToHDR/Photoshop/FileName=Merge To HDR.jsx");
var scriptFilePath = app.path + "/" + strPresets + "/" + strScripts + "/" + strMerge2HDR;
var scriptFile = new File (scriptFilePath);
var rememberDialogModes = displayDialogs;
displayDialogs = DialogModes.ALL;
if (scriptFile.exists)
{
$.evalFile( scriptFilePath );
}
else
alert (localize ("$$$/PSBI/Automate/MergeToHDR/NotFound=%1 could not be found.", strMerge2HDR));
displayDialogs = rememberDialogModes;
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//-----------------------------------------------------------------
// Runs Load Files into Stack script, providing it with all the parameters
// to this method.
//-----------------------------------------------------------------
photoshop.openAsLayersFromLightroom = function ( files,
acrDescs,
lightroomDocID,
bridgeTalkID,
saveDesc)
{
try
{
// OpenAsLayers for lightroom
var gFilesFromLightroom = files;
var gOpenParamsFromLightroom = acrDescs;
var gLightroomDocID = lightroomDocID;
var gBridgeTalkID = bridgeTalkID;
var gLightroomSaveParams = saveDesc;
var strPresets = localize ("$$$/ApplicationPresetsFolder/Presets=Presets");
var strScripts = localize ("$$$/PSBI/Automate/ImageProcessor/Photoshop/Scripts=Scripts");
var strOpenAsLayers = "Load Files into Stack.jsx";
var scriptFilePath = app.path + "/" + strPresets + "/" + strScripts + "/" + strOpenAsLayers;
var scriptFile = new File (scriptFilePath);
var rememberDialogModes = displayDialogs;
displayDialogs = DialogModes.ALL;
if (scriptFile.exists)
{
$.evalFile( scriptFilePath );
}
else
alert (localize ("$$$/PSBI/Automate/MergeToHDR/NotFound=%1 could not be found.", strOpenAsLayers));
displayDialogs = rememberDialogModes;
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//-----------------------------------------------------------------
// Runs Photomerge script, providing it with all the parameters
// to this method. Photomerge uses them when opening files,
// by invoking openFromLightroom().
//-----------------------------------------------------------------
photoshop.photomergeFromLightroom = function ( files,
acrDescs,
lightroomDocID,
bridgeTalkID,
saveDesc)
{
try
{
// Photomerge script will recognize these and use them
var gFilesFromLightroom = files;
var gOpenParamsFromLightroom = acrDescs;
var gLightroomDocID = lightroomDocID;
var gBridgeTalkID = bridgeTalkID;
var gLightroomSaveParams = saveDesc;
var strPresets = localize ("$$$/ApplicationPresetsFolder/Presets=Presets");
var strScripts = localize ("$$$/PSBI/Automate/ImageProcessor/Photoshop/Scripts=Scripts");
var strPhotomerge = localize ("$$$/PSBI/Automate/Photomerge/Photoshop/FileName=Photomerge.jsx");
var scriptFilePath = app.path + "/" + strPresets + "/" + strScripts + "/" + strPhotomerge;
var scriptFile = new File (scriptFilePath);
var rememberDialogModes = displayDialogs;
displayDialogs = DialogModes.ALL;
if (scriptFile.exists)
{
$.evalFile( scriptFilePath );
}
else
alert (localize ("$$$/PSBI/Automate/Photomerge/NotFound=%1 could not be found.", strPhotomerge));
displayDialogs = rememberDialogModes;
}
catch (error)
{
if (error.number != 8007) // Don't report user cancelled errors.
alert (error);
}
}
//-----------------------------------------------------------------
// Notify 'bridgeTalkID' that the tracked file was
// saved. Puts together an XML string including
// 'lightroomDocID' and 'path' that Lightroom will
// understand.
//-----------------------------------------------------------------
photoshop.notifyLightroomDocSaved = function (bridgeTalkID, lightroomDocID, path)
{
if (BridgeTalk.isRunning (bridgeTalkID))
{
// Create a new BridgeTalk message to notify Lightroom with
var msg = new BridgeTalk;
// use the BT id that was initially provided by LR
msg.target = bridgeTalkID;
// set a custom message type so that the message body does not get translated
// in preperation for evaluation as JavaScript
msg.type = 'PsXmlNotification';
// Create a File object and pull fsName out of it so that we end up with a POSIX style path on the Mac.
var file = new File (path);
// retrieve full path in URI notation: absolute, platform-independent, and escaped
var preparedPath = file.toString ();
// Get the substance of the notification
msg.body = photoshop.createLightroomNotificationXML ( 'FileSaved',
lightroomDocID,
preparedPath);
msg.send();
}
}
//-----------------------------------------------------------------
// Notify 'bridgeTalkID' that the tracked file was
// closed. Puts together an XML string including
// 'lightroomDocID' that Lightroom will understand.
//-----------------------------------------------------------------
photoshop.notifyLightroomDocClosed = function (bridgeTalkID, lightroomDocID)
{
if (BridgeTalk.isRunning (bridgeTalkID))
{
// Create a new BridgeTalk message to notify Lightroom with
var msg = new BridgeTalk;
// use the BT id that was initially provided by LR
msg.target = bridgeTalkID;
// set a custom message type so that the message body does not get translated
// in preperation for evaluation as JavaScript
msg.type = 'PsXmlNotification';
// Get the substance of the notification
msg.body = photoshop.createLightroomNotificationXML ( 'FileClosed',
lightroomDocID);
msg.send();
}
}
//-----------------------------------------------------------------
// Notify 'bridgeTalkID' that the file was not opened.
// Puts together an XML string including
// 'lightroomDocID' that Lightroom will understand.
//-----------------------------------------------------------------
photoshop.notifyLightroomDocNotOpened = function (bridgeTalkID, lightroomDocID, reason)
{
if (BridgeTalk.isRunning (bridgeTalkID))
{
// Create a new BridgeTalk message to notify Lightroom with
var msg = new BridgeTalk;
// use the BT id that was initially provided by LR
msg.target = bridgeTalkID;
// set a custom message type so that the message body does not get translated
// in preperation for evaluation as JavaScript
msg.type = 'PsXmlNotification';
// Get the substance of the notification
msg.body = photoshop.createLightroomNotificationXML ( 'FileNotOpened',
lightroomDocID,
null,
reason);
msg.send();
}
}
// ================================================================
// ================================================================
// ================================================================
// Utility Routines
// ================================================================
// ================================================================
// ================================================================
//-----------------------------------------------------------------
// This routine takes an array of thumbnails and returns an array of the
// files represented by those thumbnail objects.
//-----------------------------------------------------------------
photoshop.thumbnailArrayToFileArray = function (/* array of thumbnails */ thumbnails, resolveAliases, requireTwoFiles)
{
var thumbsArray = new Array ();
var filesArray = new Array ();
var foundFolder = false;
for (var index = 0; index < thumbnails.length; index++ )
{
// Don't add containers to the list, but note if any were found.
if (thumbnails[index].container)
foundFolder = true;
else
thumbsArray.push (thumbnails[index]);
}
if (thumbsArray.length == 0)
{
if (foundFolder)
Window.alert (localize ("$$$/PSBI/Automate/FoldersNotAllowed=Folders cannot be used for this command."));
else
Window.alert (localize ("$$$/PSBI/Automate/NoFiles=There are no files to process."));
}
else if (requireTwoFiles && (thumbsArray.length == 1))
{
Window.alert (localize ("$$$/PSBI/Automate/MoreThanOneRequired=This command requires two or more files."));
}
else
{
// We have adequate files, now acquire them (make sure VC files have
// a local replica) and then grab the file specs.
app.acquirePhysicalFiles (thumbsArray);
var foundAlias = false;
for (var index = 0; index < thumbsArray.length; index++ )
{
if (thumbsArray[index].spec != undefined)
{
var file = thumbsArray[index].spec;
if (resolveAliases && file.alias)
{
foundAlias = true;
file = photoshop.resolveFileIfAlias (file);
}
if (file != null)
filesArray.push (file);
}
}
// The only way filesArray.length should be zero here is if an alias could not be resolved.
// or acquire failed for some reason.
if (filesArray.length == 0)
Window.alert (localize ("$$$/PSBI/Automate/AliasNotResolved=The alias(es) could not be resolved and there are no other files to process."));
}
return filesArray;
}
//-----------------------------------------------------------------
// This routine returns the selected files, or if no files are selected,
// all the files.
//-----------------------------------------------------------------
photoshop.getBridgeFileListForAutomateCommand = function (resolveAliases, requireTwoFiles)
{
var files = new Array;
var warnNoFiles = false;
if ((app.document != undefined) && (app.document.thumbnail != undefined))
{
if (app.document.selectionLength > 0)
{
files = photoshop.thumbnailArrayToFileArray (app.document.selections, resolveAliases, requireTwoFiles);
}
else if (app.document.visibleThumbnails.length > 0)
{
files = photoshop.thumbnailArrayToFileArray (app.document.visibleThumbnails, resolveAliases, requireTwoFiles);
}
else
warnNoFiles = true;
}
else
warnNoFiles = true;
if (warnNoFiles)
Window.alert (localize ("$$$/PSBI/Automate/NoFiles=There are no files to process."));
return files;
}
//-----------------------------------------------------------------
// This routine tries to return an array of File objects created
// from the 'files' argument. It will convert a single File object
// or a single string into an array of File objects, or it will
// convert an array of string and File objects into an array of
// file objects.
//-----------------------------------------------------------------
photoshop.ExtractFileArray = function (files)
{
var fileArray = new Array;
// If it isn't an array, make it a length one array.
if (!(files instanceof Array))
files = new Array (files);
// Turn each item in the array into a File, or remove it.
for (index = 0; index < files.length; ++index)
{
var file = files[index];
if (file instanceof File)
fileArray.push (file);
else if (typeof file == 'string')
fileArray.push (File (file));
else
{
// do nothing
}
}
return fileArray;
}
//-----------------------------------------------------------------
// This routine executes the specified action. If 'settingsFileName'
// is provided, it uses any saved settings combined with the new
// file list, then saves the updated settings.
//-----------------------------------------------------------------
photoshop.runActionCommand = function (eventString,
files,
settingsFileName)
{
var eventDesc = null;
// Read in the old settings, if asked.
if (settingsFileName != null)
eventDesc = photoshop.readDescriptor (settingsFileName);
// If this is the first time we've run, there won't be a settings
// file, so create a new blank descriptor.
if (eventDesc == null)
eventDesc = new ActionDescriptor ();
if (files != null)
{
// Create an action list with the provided files and add them
// to the descriptor, overriding any previous ones that might
// have been there.
var filesListKey = stringIDToTypeID ('filesList');
var filesList = new ActionList ();
for (var index = 0; index < files.length; index++)
filesList.putPath (files[index]);
eventDesc.putList (filesListKey, filesList);
filesList = null; // garbage collect this below
}
// Force it to record.
var forceRecordKey = stringIDToTypeID ('forceRecording');
eventDesc.putBoolean (forceRecordKey, true);
// Run the action.
var eventKey = stringIDToTypeID (eventString);
var resultDesc = executeAction (eventKey, eventDesc, DialogModes.ALL);
// Don't record the action for Batch
if (eventString == 'batch')
resultDesc.erase (stringIDToTypeID ('using'));
// Save the descriptor for next time, if asked.
if (settingsFileName != null)
photoshop.saveDescriptor (settingsFileName, resultDesc);
// force deletion of descriptor and list now
eventDesc = null;
$.gc();
}
//-----------------------------------------------------------------
// This routine saves the given descriptor to a settings file using
// the given name.
//-----------------------------------------------------------------
photoshop.saveDescriptor = function (name, descriptor)
{
// try-catch this routine so if something goes terribly wrong
// we can still run the command.
try
{
if ((descriptor == null) || (descriptor.count == 0))
return;
var folder = photoshop.getActionCmdSettingsFolder ();
if (!folder.exists && !folder.create ())
return;
var stream = descriptor.toStream ();
var file = new File (folder.fsName + "/" + name + '.psp');
if (file.open ('w'))
{
file.encoding = 'BINARY';
file.write (stream);
file.close ();
}
}
catch (e)
{
return null;
}
}
//-----------------------------------------------------------------
// This routine retrieves a descriptor from a settings file using
// the given name. A descriptor ought to have been previously saved
// under the same name using saveDescriptor ().
//-----------------------------------------------------------------
photoshop.readDescriptor = function (name)
{
// try-catch this routine so if something goes terribly wrong
// we can still run the command.
try
{
var folder = photoshop.getActionCmdSettingsFolder ();
var file = new File (folder.fsName + "/" + name + '.psp');
if (!file.exists)
return null;
if (!file.open ('r'))
return null;
file.encoding = 'BINARY';
var stream = file.read (file.length);
file.close ();
var descriptor = new ActionDescriptor ();
descriptor.fromStream (stream);
return descriptor;
}
catch (e)
{
return null;
}
}
//-----------------------------------------------------------------
// This routine retrieves a descriptor from a settings file using
// the given name. A descriptor ought to have been previously saved
// under the same name using saveDescriptor ().
//-----------------------------------------------------------------
photoshop.getActionCmdSettingsFolder = function ()
{
var settingsFolder = new Folder (app.preferencesFolder);
if (!settingsFolder.exists)
settingsFolder.create ();
return settingsFolder;
}
//-----------------------------------------------------------------
// This routine creates and returns a BridgeTalk message that will
// invoke Bridge and tell it what to do based on the arguments. It
// is wrapped in a utility function because it is used by multiple
// other routines.
//-----------------------------------------------------------------
photoshop.getInvokeBridgeMessage = function (path, wasRunning)
{
var bt = new BridgeTalk;
bt.target = photoshop.versionInfo.bridgeTarget;
// If there is no path, we want to pass nothing to Bridge's routines,
// not an empty File object.
var file = '';
// toSource is our friend. The 'path' string may have quotes (single or double)
// in it that start messing things up if we want to use it as part of a bigger
// string (in particular part of a BridgeTalk message body); specifically, string
// literals can get terminated early leading to syntax errors. So, we create
// a File object out of it and call toSource on the File object to get back a
// string that can be used as part of a larger string (nasty characters like
// quotes will be replaced with URL friendly equivalents).
// encodeURI does us one better in making sure some additional characters pass
// across the wire successfully.
if (path != null && path != '')
file = File (encodeURI(path)).toSource ();
if (wasRunning)
{
// Create a function that we can pass across to Bridge in a BridgeTalk message.
// This allows us to write more freely than trying to construct a string with it.
// Comments in this function must be of the /* */ form because toSource() is
// not preserving white space so // comments will kill subsequent lines
var bridgeScript = function (file)
{
if (file != null)
{
if (app.documents.length > 0)
{
/* New location for existing window, make sure existing window comes forward */
app.document.thumbnail = new Thumbnail (file);
app.document.bringToFront();
}
else
{
/*
New window with location.
Bring new window to front is required if BR is minimized on Windows
*/
var newDoc = new Document (file);
newDoc.bringToFront();
}
}
else
{
if (app.documents.length == 0)
{
/*
New window with default location, only occurs on Mac where you can have zero BR windows.
Document constructor requires a parameter
*/
new Document (File());
}
else
{
/* Just bring the exist doc forward at it's existing location */
app.document.bringToFront();
}
}
} // bridgeScript
// Turn the function into a string and call it directy with the appropriate parameters
bt.body = bridgeScript.toSource() + "(" + file + ")";
}
else
{
// New location for default window
bt.body = "app.document.thumbnail = new Thumbnail (" + file + ");";
}
return bt;
}
//-----------------------------------------------------------------
// Returns true if the required version of Bridge is installed.
//-----------------------------------------------------------------
photoshop.correctBridgeIsAvailable = function (showUI)
{
var result = false;
if (BridgeTalk.isRunning (photoshop.versionInfo.bridgeTarget))
{
// It's running, so it is definitely available!
result = true;
}
else
{
// We cannot ask for the Bridge specifier in a minor-version agnostic way, so now that
// Bridge uses specifiers like bridge-5.032 and bridge-5.064 we can't simply see if
// BridgeTalk.getSpecifier ('bridge') returns null.
// Instead, ask for the specifier without a version which should give us back a
// version associated with this version of Photoshop. Then test to ensure the version
// meets the minimum requirement.
var bridgeSpecifier = BridgeTalk.getSpecifier ('bridge');
var isMinimumRequiredVersionInstalled = Number(bridgeSpecifier.split("-")[1]) >= photoshop.versionInfo.bridgeMinimumRequiredTargetVersion;
if (bridgeSpecifier == null || isMinimumRequiredVersionInstalled == false)
{
if (showUI)
alert (localize ("$$$/PSBI/Error/MatchingBridgeVersionNotInstalled/2025=Bridge was not found on this system. To use this command, please reinstall Bridge."));
result = false;
}
else
{
// The target version is installed and should be launchable, unless a different version
// is running, which we cannot reliable detect. Hope that is not the case.
result = true;
}
}
return result;
}
//-----------------------------------------------------------------
// Returns true if the required version of Bridge is installed.
//-----------------------------------------------------------------
photoshop.correctExtensionManagerIsAvailable = function ()
{
var result = false;
if (BridgeTalk.isRunning (photoshop.versionInfo.extensionManagerTarget))
{
// It's running, so it is definitely available!
result = true;
}
else
{
// extension manager uses moniker like exman-7.0
var bridgeSpecifier = BridgeTalk.getSpecifier ('exman');
var expectedSpecifierStart = 'exman-' + photoshop.versionInfo.extensionManagerTargetVersion;
if (bridgeSpecifier == null ||
bridgeSpecifier.indexOf (expectedSpecifierStart) != 0)
{
// extension manager is not installed
result = false;
}
else
{
// The target version is installed and should be launchable, unless a different version
// is running, which we cannot reliable detect. Hope that is not the case.
result = true;
}
}
return result;
}
//-----------------------------------------------------------------
// Returns true if the required version of Photoshop is available
// to execute a command in the sense that it is installed and
// running or can be launched. It also indicates that it is
// ready to process a command (not busy) or that the user has
// requested that the command be queued even though Photoshop is
// busy.
//-----------------------------------------------------------------
photoshop.correctPSIsAvailable = function (checkOptions)
{
// If no options are passed in, use default ones.
if (checkOptions == null)
{
checkOptions = new AvailabilityCheckOptions ();
}
else
{
if (checkOptions.alreadyUsed == true)
return checkOptions.alreadyUsedReturnValue;
}
var result = false;
// No need to check to see if the correct version is installed because if it
// isn't installed then this script doesn't get loaded, except inside of the
// correct version of Photoshop if it really is installed (and its registration
// with BridgeTalk is broken).
if (BridgeTalk.appName == "photoshop")
{
if (BridgeTalk.appVersion.indexOf (photoshop.versionInfo.rootVersion) == 0)
{
// This script is running in the target version of PS.
result = true;
}
else
{
// We are running inside a different version of PS than what is required. This really
// shouldn't happen because this script shouldn't load in a version other than
// the required version.
if (checkOptions.warnIfUnavailable)
alert (checkOptions.warnInsidePSText);
}
}
else if (BridgeTalk.isRunning (photoshop.versionInfo.btTargetName))
{
// Above is a quick test to see if it is running. If it is, it can be messaged if necessary.
var status = BridgeTalk.ping (photoshop.versionInfo.btTargetName, "STATUS");
if (status != "IDLE")
{
if (checkOptions.busyAction == AvailabilityCheckOptions.kBusyWarn)
{
alert (checkOptions.warnBusyText);
result = false;
}
else if (checkOptions.busyAction == AvailabilityCheckOptions.kBusyAsk)
{
result = confirm (checkOptions.askBusyText);
}
else if (checkOptions.busyAction == AvailabilityCheckOptions.kBusyAutoQueue)
result = true;
else // AvailabilityCheckOptions.kBusyAutoCancel
result = false;
}
else
result = true;
}
else
{
// The target version is installed and should be launchable, unless a different version
// is running, which we cannot reliable detect. Hope that is not the case.
result = true;
}
checkOptions.alreadyUsed = true;
checkOptions.alreadyUsedReturnValue = result;
return result;
}
//-----------------------------------------------------------------
// If file is an alias: returns file's target if file is
// successfully resolved and the target exists, otherwise null. If
// file is not an alias: returns file.
//-----------------------------------------------------------------
photoshop.resolveFileIfAlias = function (file)
{
if (file.alias)
{
try
{
file = file.resolve ();
}
catch (e)
{
file = null;
}
// On Windows, a shorcut may get resolved even if the target file doesn't exist
if ((file != null) && !file.exists)
file = null;
}
return file;
}
//-----------------------------------------------------------------
// Creates and returns a 'PSFileStatusChange' XML string formatted
// for Lightroom to receive and interpret.
//-----------------------------------------------------------------
photoshop.createLightroomNotificationXML = function (message, identifier, path, reason)
{
var xmlString = '<?xml version="1.0" encoding="UTF-8"?>'; // processing instructions
xmlString += '\n<PSFileStatusChange version="1.0"';
xmlString += '\n message="' + message + '"';
if (reason != null)
xmlString += '\n reason="' + reason + '"';
xmlString += '\n identifier="' + identifier + '"';
if (path != null)
xmlString += '\n path="' + path + '"';
xmlString += ' />'
return xmlString;
}
} // Overall try catch
catch (e)
{
// Debugging
// alert (e + ": line " + e.line);
}