0.0.5 • Published 2 years ago

photoshop-script v0.0.5

Weekly downloads
-
License
ISC
Repository
github
Last release
2 years ago

photoshop-script


fork from after-effects and modified to be compatible with photoshop.

Why?

  • You're running a node.js server with After Effects installed, and you'd like to run render commands server-side.

  • You use node.js locally, and prefer not to run PS scripts with the ExtendScript toolkit.

  • You'd like to run and create PS scripts using ES6 syntax.

  • Because it angers your religious mother, and you want to be rebellious.

Requirements

Obviously, you need After Effects installed on your machine. Additionally, in your After Effects preferences, enable:

Preferences -> General -> Allow Scripts to Write Files and Access Network


Basic Usage

var ps = require("photoshop");

Ta Daaaa. The rest of this readme assumes ps is the after effects module.

To execute some code in After Effects:

ps(() => alert("Hello!\nFrom node.js"));

What fun!

Provided that After Effects is installed in your Applications/Program directory, and that you haven't renamed any of the folders or something, this will work.


Scripting Considerations

The After Effects scripting environment is a completely different engine than node.js. Node.js has no access to the After Effects environment, and vice versa:

var foo = "bar";

//this will not work:
ps(() => alert(foo));

If you'd like to send data from node.js to After Effects, you have to supply it as an argument along with the execute command:

var foo = "bar";

ps((foo_from_node) => alert(foo_from_node), foo);

What you're really doing when you use the execute method is converting the supplied function to a string and then sending it to After Effects to parse. As a result, whatever data you supply has to be convertible to JSON.

You can also retrieve data from After Effects with the same restriction:

var project_name = ps(() => {
    if (app.project.file)
        return app.project.file.name;
    else
        return "(project not yet saved)";
});

console.log(project_name);

Also see the After Effects Scripting Guide for information about the After Effects Javascript API.


Sync vs Async

The default shortcut function will run the code synchronously and block NodeJS until complete, however, you can also send code to After Effects asynchronously:

//execute sends code to after effects, returning a Promise
ps.execute(() => {
  return app.project.activeItem.name;
})
.then(name => console.log(name))
.catch(err => console.log('No Active Item'));

The default shortcut function actually is just a shortcut to ps.executeSync:

function save_current_project() {
  app.project.save();
}

ps.executeSync(save_current_project);
//is the same as
ps(save_current_project);

Options

The ps object has a couple of options:

ps.options.errorHandling = true;
ps.options.minify = false;
ps.options.program = null;
ps.options.includes = [
    './node_modules/photoshop/lib/includes/console.jsx',
    './node_modules/photoshop/lib/includes/es5-shim.jsx',
    './node_modules/photoshop/lib/includes/get.jsx'
]

This would be how you set defaults.

errorHandling

With errorHandling enabled, errors thrown in After Effects will be suppressed and returned in the promise result:

ps.options.errorHandling = true;

ps.execute(() => throw new Error("FooBar got FooBarred all the way to FooBar."))
.then(result => console.log(result)) // empty
.catch(err => console.log(err)); // contains error

With errorHandling disabled, After Effects will create a popup and prevent further code execution until it is dealt with.

minify

If true, the code will be minified before being sent to After Effects. This is disabled by default, which is different from previous versions of this package. I feel there's little point in spending the extra time to minify code that isn't going over a network. Still, you can set minify to true if you're into that sort of thing.

ps.options.minify = true;

program

By default, ps will look for an After Effects installation in your platforms default application directory. If you've installed it elsewhere, you'll have to set this to the custom app directory.

ps.options.program = path.join('OtherAppDirectory','Adobe After Effects 2015');

Also handy if you've installed multiple versions of After Effects on your machine, and you'd like to target a specific one.

includes

Includes is an array which will concatanate the code from other files into your command, for use inside After Effects. The defaults are as follows:

console.js

Provides console.log to the After Effects namespace. 'console.log' inside After Effects will return logs to the node.js console when execution is complete, assuming you correctly have Preferences -> General -> Allow Scripts to Write Files and Access Network set inside After Effects.

es5-shim.js

The javascript environment within After Effects is very dated, pre ES5. With es5-shim included, methods and functions available in es5 will be available.

ps.execute(() => {
    [1,2,3,4].forEach(i => alert(i)); // wont throw an error
});

Also notice that you can use ES6 syntax when executing code. It's parsed through babel before being sent to After Effects.

Include Considerations

The default options exist in their current state to benefit quickstarting. I just want to fire up atom and run an ps command without thinking too much about it. That said, there are a couple of things you can do to optimize it's usage.

Persistent Environment

The scripting environment inside After Effects persists between executions, unless you manually reset it or restart After Effects.

ps(()=> console.log('includes ran'));
ps.options.includes = [];

//Once you've run your includes,
//you can disable them and still benefit from their usage in the namespace:
ps(()=> ["shim","still","exists"].forEach(str => alert(str)));

You have access to the After Effects global namespace, through $.global:

ps(() => $.global.whoKilledKenny = "you bastards");

var who = ps(() => $.global.whoKilledKenny);
console.log(who); //you bastards

Scripts directory

There is a convenience method to get the scripts directory associated with the current After Effects install:

console.log(ps.scriptsDir);

This will throw an error if After Effects can't be found. This is useful if you want to include any scripts in the Scripts Directory that might exist.

Startup Folder

Alternatively, You can copy the scripts provided in the lib folder to the After Scripts/Startup folder inside your After Effects installation. Then will be run and added to the global namespace when After Effects is starting, and will not have to be included while executing commands from ps.

.jsx vs .js

If you just installed After Effects, you'll notice that all of the files in the Scripts Directory end in .jsx If you're familiar with React, you're probably wondering what the hell they're doing there. Well, long before Facebooks React, Adobe's primary javascript format was .jsx. This is because the Adobe javascript Engine has an xml literal built into it:

var xml = <foo><bar/></foo>

We can't take advantage of that xml literal inside nodejs because babel doesn't have a preset for it. As a result, if you try to include a .jsx file, ps will assume it's written in Adobe Javascript. ps will not babelify or minify it, otherwise it will could cause errors if the XML literal was used.


Advanced Usage

If you're going to execute a particular method frequently, you can precompile it as a command, which will prevent it from having to be babelified or minified again:

var create_composition = new ps.Command(name => {
  name = typeof name === "string" ? name : "New Comp";
  app.project.items.addComp(name, 1920, 1080, 1, 24, 10);
});

Commands, once made, can be executed with different arguments:

ps(create_composition, "First Comp");
//or
ps.execute(create_composition, "Super Comp");
//or
create_composition.executeSync("Oh we got ourselves a badass here");
//you get the idea
create_composition.execute("Breast Milk");

Commands have their own set of options. By default, they are the same as the options set on ps.options:

ps.options.minify = true;

var getNumItems = new ps. Command(() => app.project.numItems); //will minify

Command options cannot be changed:

ps.options.errorHandling = false;
var breakForFun = new ps.Command(() => throw("This is MY house."));

ps.options.errorHandling = true;

breakForFun.executeSync(); // will still alert inside in PS
breakForFun.errorHandling = true; //throws error

You can create commands with their own options:

var getProjectName = new ps.Command(()=> app.project.file.name, { includes: null, minify: true });

Creating Scripts

Rather than executing code, you can create scripts for use in After Effects:

 ps.create(() => {

    let say_name =  item => alert(item.name);
    say_name(app.project.activeItem);

 }, "SayName.jsx");

This script will be available for After Effects to use in it's scripts folder. The filename provided will be treated as a relative URI, so if you want to create a script in the Scripts/Startup folder:

 ps.create(() => {

   alert("After Effects totally just started.");

 }, "Startup/SayHello.jsx");

If you'd like to place scripts somewhere other than the scripts folder, you can pass an absolute path:

 ps.create(() => {

    app.project.activeItem.remove(); 
 }, path.join(__dirname, "Created Scripts", "DeleteActiveItem.jsx")); 

You can also create a script out of a command, with baked arguments:

var renameActiveItem = new ps.Command( name => app.project.activeItem.name = name);
ps.create(renameActiveItem, "RenameActiveItemLarry.jsx", "Larry");

If you don't provide a filetype exention scripts will be created as .jsx by default. After Effects doesn't care what the filetype extension is, but you might as well leave it as .jsx by convention.

You can also create scripts syncronously with ps.createSync();


Version 0.4.0

Windows support has been added, but hasn't been tested rigorously. Input about broken/undocumented functionality is highly welcome, especially from windows users.