#target photoshop-70 // (c) Copyright 2014. Adobe Systems, Incorporated. All rights reserved. /* @@@BUILDINFO@@@ photoshop.jsx 1.0.6 8-Sept-2021 */ /* @@@START_XML@@@ Adobe Photoshop This script enables other applications to communicate with Adobe Photoshop. Adobe Photoshop Ce script permet à d'autres applications de communiquer avec Adobe Photoshop. Adobe Photoshop このスクリプトは、他のアプリケーションと Adobe Photoshop との通信を有効にします。 Adobe Photoshop Mithilfe dieses Skripts können andere Anwendungen mit Adobe Photoshop kommunizieren. Adobe Photoshop Questo script consente ad altre applicazioni di comunicare con Adobe Photoshop. Adobe Photoshop Este script posibilita que otras aplicaciones se comuniquen con Adobe Photoshop. Adobe Photoshop Dit script laat andere toepassingen toe te communiceren met Adobe Photoshop. Adobe Photoshop Este script permite que outros aplicativos se comuniquem com o Adobe Photoshop. Adobe Photoshop Skriptet gjør at andre programmer kan kommunisere med Adobe Photoshop. Adobe Photoshop Dette script betyder, at andre programmer kan kommunikere med Adobe Photoshop. Adobe Photoshop Tämän komentosarjan avulla muut sovellukset ja Adobe Photoshop voivat kommunikoida keskenään. Adobe Photoshop Det här skriptet gör det möjligt för andra program att kommunicera med Adobe Photoshop. Adobe Photoshop 此指令碼能讓其他應用程式與 Adobe Photoshop 進行通訊。 Adobe Photoshop 此脚本使其它应用程序能够与 Adobe Photoshop 进行通信。 Adobe Photoshop 이 스크립트를 사용하면 다른 응용 프로그램에서 Adobe Photoshop과(와) 통신할 수 있습니다. Adobe Photoshop يتيح هذا النص التنفيذي للتطبيقات الأخرى أن تتصل بـ Adobe Photoshop. Adobe Photoshop Tento skript umožňuje dalším aplikacím komunikovat s aplikací Adobe Photoshop. Adobe Photoshop Αυτή η δέσμη ενεργειών δίνει τη δυνατότητα σε άλλες εφαρμογές να επικοινωνούν με το Adobe Photoshop. Adobe Photoshop Este script posibilita que otras aplicaciones se comuniquen con Adobe Photoshop. Adobe Photoshop Ce script permet à d'autres applications de communiquer avec Adobe Photoshop. Adobe Photoshop Ce script permet à d'autres applications de communiquer avec Adobe Photoshop. Adobe Photoshop סקריפט זה מאפשר ליישומים אחרים לתקשר עם Adobe Photoshop. Adobe Photoshop Ez a parancsfájl gondoskodik arról, hogy más alkalmazások kommunikálhassanak az Adobe Photoshop programmal. Adobe Photoshop Ten skrypt umożliwia innym aplikacjom komunikowanie się z programem Adobe Photoshop. Adobe Photoshop Acest script permite altor aplicaţii să comunice cu Adobe Photoshop. Adobe Photoshop Этот сценарий позволяет другим приложениям обмениваться данными с Adobe Photoshop. Adobe Photoshop Bu komut dosyası, diğer uygulamaların Adobe Photoshop ile iletişim kurmasını sağlar. Adobe Photoshop Цей сценарій забезпечує обмін даними між Adobe Photoshop та іншими програмами. Adobe Photoshop This script enables other applications to communicate with Adobe Photoshop. Adobe Photoshop This script enables other applications to communicate with Adobe Photoshop. Adobe Photoshop Ce script permet à d'autres applications de communiquer avec Adobe Photoshop. @@@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 = 7; tempPSVersionInfo.btTargetName = 'photoshop'; // no version so BT can resolve to .032 or .064 as needed tempPSVersionInfo.rootVersion = '70.0'; // no minor version so we can match against .032 or .064 as needed tempPSVersionInfo.displayVersion = 'CC'; // does not get localized tempPSVersionInfo.bridgeTargetVersion = '6'; tempPSVersionInfo.bridgeTarget = 'bridge'; tempPSVersionInfo.bridgeDisplayVersion = 'CC'; // does not get localized tempPSVersionInfo.extensionManagerTargetVersion = '7'; tempPSVersionInfo.extensionManagerTarget = 'exman'; //----------------------------------------------------------------- // Guard against loading in non-matching version of PS. // Adding this check to CC script revved for CC 2014.1 (15.1) so that we can avoid wasting time // loading this script in PS only to override it with the 2014 version of the startup script (it // will still load then be overridden by the 2014 startup script inside of Bridge and other apps). //----------------------------------------------------------------- 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 photoshop; 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 photoshop60 object equal to the generic photoshop object // so photoshop60.foo() can be used. photoshop70 = 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. //================================================================= photoshop.invokeBridge = function (newWindow, maximize, 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 (newWindow, maximize, 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", photoshop.versionInfo.bridgeTargetVersion); var bridgeVersion = null; if (bridgeSpecifier != null) bridgeVersion = bridgeSpecifier.match (/[0-9\.]+/); // 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) { 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 () + ");"; 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); // 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); } } //----------------------------------------------------------------- // The code below inserts the Place in Photoshop menu item into the // place menu and sets up the onSelect routines for it. //----------------------------------------------------------------- if ((BridgeTalk.appName == "bridge") && (BridgeTalk.appVersion.indexOf (photoshop.versionInfo.bridgeTargetVersion) == 0)) { // Use temp function to keep vars out of global namespace. photoshop.tempFunction = function () { // insert a new Place In Photoshop menu item into the Place submenu. var placeMenuItem = MenuElement.create ("command", localize ("$$$/PSBI/Menu/Place/InPhotoshop=In Photoshop"), 'at the end of submenu/Place', 'PlaceInPhotoshop'); placeMenuItem.onSelect = function () { try { if ((app.document == undefined) || (app.document.visibleThumbnails.length <= 0)) { Window.alert (localize ("$$$/PSBI/Automate/NoFiles=There are no files to process.")); return; } // check selection length before asking for selections (better performance) if (app.document.selectionLength != 1) { Window.alert (localize ("$$$/PSBI/Place/SelectOneFile=Please select a single file.")); return; } var selections = app.document.selections; if (!selections[0].container) { // Make sure this can be run. var 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; var thumb = selections[0]; app.acquirePhysicalFiles (Array (thumb)); if (thumb.spec == undefined) { Window.alert (localize ("$$$/PSBI/Place/AliasNotResolved=The alias could not be resolved.")); return; } var file = photoshop.resolveFileIfAlias (thumb.spec); if (file != null) photoshop.place (file, availabilityCheckOptions); else Window.alert (localize ("$$$/PSBI/Place/AliasNotResolved=The alias could not be resolved.")); } else { if (app.document.selectionLength == 1) Window.alert (localize ("$$$/PSBI/Automate/FoldersNotAllowed=Folders cannot be used for this command.")); else Window.alert (localize ("$$$/PSBI/Place/SelectOneFile=Please select a single file.")); } } catch (error) { if (error.number != 8007) // Don't report user cancelled errors. alert (error); } } } photoshop.tempFunction (); delete photoshop.tempFunction; } //================================================================= // 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); } } //----------------------------------------------------------------- // The code below inserts the Photomerge menu item into the // Bridge menus. //----------------------------------------------------------------- if ((BridgeTalk.appName == "bridge") && (BridgeTalk.appVersion.indexOf (photoshop.versionInfo.bridgeTargetVersion) == 0)) { // 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/Photomerge=Photomerge..."); menuItemInfo.name = 'Photomerge'; menuItemInfo.onSelect = photoshop.photomergeFromBridge; photoshop.menuItemInfoArray.push (menuItemInfo); } photoshop.tempFunction (); delete photoshop.tempFunction; } //================================================================= // 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); } } //----------------------------------------------------------------- // The code below inserts the Contact Sheet menu item into the // Bridge menus. It requires the optional Photoshop ContactSheetII // 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") && (BridgeTalk.appVersion.indexOf (photoshop.versionInfo.bridgeTargetVersion) == 0)) { // 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/ContactSheet=Contact Sheet II..."); menuItemInfo.name = 'ContactSheet'; menuItemInfo.onSelect = photoshop.contactSheetFromBridge; photoshop.menuItemInfoArray.push (menuItemInfo); } photoshop.tempFunction (); delete photoshop.tempFunction; } ----------------------------- END -------------------------------*/ //================================================================= // 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") && (BridgeTalk.appVersion.indexOf (photoshop.versionInfo.bridgeTargetVersion) == 0)) { // 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); } } //----------------------------------------------------------------- // The code below inserts the Batch menu item into the Bridge menus. //----------------------------------------------------------------- if ((BridgeTalk.appName == "bridge") && (BridgeTalk.appVersion.indexOf (photoshop.versionInfo.bridgeTargetVersion) == 0)) { // 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/Batch=Batch..."); menuItemInfo.name = 'Batch'; menuItemInfo.onSelect = photoshop.batchFromBridge; photoshop.menuItemInfoArray.push (menuItemInfo); } photoshop.tempFunction (); delete photoshop.tempFunction; } //----------------------------------------------------------------- // 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); } } //----------------------------------------------------------------- // The code below inserts the Load Files into Photoshop Layers menu item into the // Bridge menus. //----------------------------------------------------------------- if ((BridgeTalk.appName == "bridge") && (BridgeTalk.appVersion.indexOf (photoshop.versionInfo.bridgeTargetVersion) == 0)) { // 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/LoadFilesToLayers=Load Files into Photoshop Layers..."); menuItemInfo.name = 'LoadFilesIntoLayers'; menuItemInfo.onSelect = photoshop.loadFilesIntoStackFromBridge; photoshop.menuItemInfoArray.push (menuItemInfo); } photoshop.tempFunction (); delete photoshop.tempFunction; } //================================================================= // 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); } } //----------------------------------------------------------------- // The code below inserts the Lens Correction menu item into the // Bridge menus. //----------------------------------------------------------------- if ((BridgeTalk.appName == "bridge") && (BridgeTalk.appVersion.indexOf (photoshop.versionInfo.bridgeTargetVersion) == 0)) { // 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 ("$$$/JavaScripts/LensCorrect/Menu=Lens Correction..."); menuItemInfo.name = 'LensCorrect'; menuItemInfo.onSelect = photoshop.lensCorrectFromBridge; photoshop.menuItemInfoArray.push (menuItemInfo); } photoshop.tempFunction (); delete photoshop.tempFunction; } //================================================================= // 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); } } //----------------------------------------------------------------- // The code below inserts the Merge to HDR menu item into the // Bridge menus. //----------------------------------------------------------------- if ((BridgeTalk.appName == "bridge") && (BridgeTalk.appVersion.indexOf (photoshop.versionInfo.bridgeTargetVersion) == 0)) { // 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/MergeToHDR=Merge to HDR Pro..."); menuItemInfo.name = 'MergeToHDR'; menuItemInfo.onSelect = photoshop.mergeToHDRFromBridge; photoshop.menuItemInfoArray.push (menuItemInfo); } photoshop.tempFunction (); delete photoshop.tempFunction; } //================================================================= // 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); } } //----------------------------------------------------------------- // The code below inserts the Image Processor menu item into the // Bridge menus. //----------------------------------------------------------------- if ((BridgeTalk.appName == "bridge") && (BridgeTalk.appVersion.indexOf (photoshop.versionInfo.bridgeTargetVersion) == 0)) { // 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/ImageProcessor=Image Processor..."); menuItemInfo.name = 'ImageProcessor'; menuItemInfo.onSelect = photoshop.imageprocessorFromBridge; photoshop.menuItemInfoArray.push (menuItemInfo); } photoshop.tempFunction (); delete photoshop.tempFunction; } //================================================================= // 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") && (BridgeTalk.appVersion.indexOf (photoshop.versionInfo.bridgeTargetVersion) == 0)) { // 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); 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 (newWindow, maximize, 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 (newWindow, maximize, file) { if (file != null) { if (!newWindow && 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 if (newWindow) { /* New window with location. Bring new window to front is required if BR is minimized on Windows */ var newDoc = new Document (app.document.thumbnail); newDoc.bringToFront(); } else { /* Just bring the exist doc forward at it's existing location */ app.document.bringToFront(); } } /* Maximize if requested */ if (maximize) app.document.maximize(); } // bridgeScript // Turn the function into a string and call it directy with the appropriate parameters bt.body = bridgeScript.toSource() + "(" + newWindow + ", " + maximize + ", " + file + ")"; } else { // this conflicts with the maximize call when file is empty, so don't do it then if (file) bt.body = "app.document.thumbnail = new Thumbnail (" + file + ");"; if ($.os.charAt (0) == 'W') { // On Windows, holding any key down when launching an app makes it // launch behind the current one. Since we support modifiers when // invoking bridge, this is problematic. To avoid this unwanted // behavior, we get Bridge to send a message back to Photoshop with // the body "BridgeTalk.bringToFront ('bridge')". If a key was held // down then Photoshp still has focus and the call will bring Bridge // to the foreground. If a key was not held down, then the call does // nothing. bt.body += "var bt = new BridgeTalk;" + "bt.target = '" + photoshop.versionInfo.btTargetName + "';" + "bt.body = '" + 'BridgeTalk.bringToFront ("' + photoshop.versionInfo.bridgeTarget + '")' + "';" + "bt.send ();"; } } if (maximize) bt.body += "app.document.maximize ();"; 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', photoshop.versionInfo.bridgeTargetVersion) 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 // matches what we expect. var bridgeSpecifier = BridgeTalk.getSpecifier ('bridge'); var expectedSpecifierStart = 'bridge-' + photoshop.versionInfo.bridgeTargetVersion; if (bridgeSpecifier == null || bridgeSpecifier.indexOf (expectedSpecifierStart) != 0) { if (showUI) alert (localize ("$$$/PSBI/Error/MatchingBridgeVersionNotInstalled=Bridge %1 was not found on this system. To use this command, please reinstall Bridge %1.", photoshop.versionInfo.bridgeDisplayVersion)); 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 = ''; // processing instructions xmlString += '\n