Pixelmator Pro gets AppleScript support

Discuss the latest Pixelmator news.
User avatar

2020-09-17 13:09:26

Hey everyone! Big news from the Pixelmator Team, today we’re releasing a major update to Pixelmator Pro. Version 1.8, codenamed Lynx, is now here, bringing incredibly full-featured support for AppleScript.



Read the full post on our blog.
User avatar

2020-09-18 05:42:04

If I was a hacker or coder this would be amazing I think, sounds amazing at least!
User avatar

2020-09-18 13:17:05

Even if you're not familiar (or only a little familiar with programming), AppleScript is pretty accessible! At least I think it is.
User avatar

2020-09-21 15:18:23

ML is a good feature but consistently crashes my app, even on resizing elements within a file.
Because ML takes so long, a designated 'DING' at finish would be useful.
We should also be able to see CALCULATED FILE SIZE when creating or resizing a file.
I'd like to know DOCUMENT SIZE while working, not dimensions, I know those, I want size.
How do we not have a HISTORY?! We have no idea where we are without HISTORY.
Your own FONTS would be cool. Even as an extension pack.
The GUI is often buggy, I have to find workarounds when things like FILL don't work, or the color changes back.
Am I alone in wanting a SAVE AS choice so I can stop duplicating all my documents?
Please fix BLUR so we can use it functionally without having to know about the option key.
SMUDGE doesn't do anything! I paint with smudge, that's my painting tool, but there is ZERO smudge in MacOS!
Despite these shortcomings thank u for a workable product.
User avatar

2020-10-08 00:06:37

It’s great that Pixelmator Pro has added examples to its AppleScrip dictionary. It's like the first useful dictionary.

I want to select a specific color and maybe a shape if that's possible.

I referenced the dictionary for the “load selection” command.
--> tell the front document to load selection mode add selection

I think I need “tell the front document to load selection mode new selection”

I assume I need to pass parameters, but I’m unsure of how to do that? Maybe you could explain?
User avatar

2020-10-08 07:43:50

"Load selection" is a layer-level command, so it looks like that particular dictionary example is actually wrong. My bad! I think I may have written that when I was just getting started with AppleScript...

Anyway, since it's a layer-level command, you'd need to make sure your script does say which layer's outline should be selected. You could do it like this:
tell application "Pixelmator Pro"
	tell the front document to tell the first layer to load selection
end tell
Or this:
tell application "Pixelmator Pro"
	tell the front document
		load selection of the first layer
	end tell
end tell
Or this:
tell application "Pixelmator Pro"
	load selection of the first layer of the front document
end tell
Or even this:
tell application "Pixelmator Pro"
	tell the front document
		tell the first layer
			load selection
		end tell
	end tell
end tell
Note how, in each case, I'm loading the outline of the first layer as a selection. Of course, you can select the outline of any layer you like. Also, if you're creating a new selection, you don't need to say "mode new selection", that's already the default.
User avatar

2020-10-08 15:06:00

Andrius, thank you for the fast reply and for providing so many examples. I will be using that command, but Is it also possible to load a new selection of every occurrence of a specific color?

For example:

tell application "Pixelmator Pro"
tell the front document to tell the first layer to load selection with properties {color: {0, 0, 0}}
end tell


FYI, I'm new to Pixelmator Pro, and it's impressive. I started on this path through your AppleScript contest that was highlighted by Late Night Software. All good stuff!
User avatar

2020-10-09 07:38:13

Yeah, you should be able to do this. If I've understood correctly, you have a document with multiple layers of various colors and you'd like to create a selection from all the layers of a certain color? If so, are the layers vector layers or image layers? If they're vector layers, you could, in theory, get their fill color property and check it that way. Otherwise, you'd be better off using the pick color command to check the color of a certain point in the image and, if it matches, load a selection of that layer, adding it to an existing selection. In fact, as that way is more versatile, it's probably worth just using that in every case. Anyway, here's what that would look like:
tell application "Pixelmator Pro"
	tell the front document
		repeat with a from 1 to number of layers
			set layerColor to pick color at position of layer a
			if layerColor = {0, 41634, 65535, 65535} then
				load selection of layer a mode add selection
			end if
		end repeat
	end tell
end tell
A more concise way of writing that would be:
tell application "Pixelmator Pro"
	tell the front document
		repeat with a from 1 to number of layers
			if (pick color at position of layer a) = {0, 41634, 65535, 65535} then
				load selection of layer a mode add selection
			end if
		end repeat
	end tell
end tell
A few notes: the position of a layer is determined by its top left point, so right now pick color will pick its top left pixel. That's fine for rectangular layers, but terrible for circles and pretty much all other shapes. To fix that, we can get the position and add half of the width to the x value and half of the height to the y value, i.e. pick a color from the center of the layer:
tell application "Pixelmator Pro"
	tell the front document
		repeat with a from 1 to number of layers
			set {x, y} to position of layer a
			set {w, h} to {width, height} of layer a
			set centerOfCurrentLayer to {x + (w / 2), y + (h / 2)}
			if (pick color at centerOfCurrentLayer) = {0, 41634, 65535, 65535} then
				load selection of layer a mode add selection
			end if
		end repeat
	end tell
end tell
Another thing: pick color returns an RGBA value, i.e. red, green, blue, and alpha. If you don't care about transparency, you could get the first three values returned by pick color, then write the if condition like this:
set {r, g, b} to pick color at centerOfCurrentLayer
if {r, g, b} = {0, 41634, 65535} then
Also, if you have experience with AppleScript, you probably already know this already but, just in case – because color values can be 8-bit or 16-bit, 16-bit ones are always used by default in AppleScript. In my example script {0, 41634, 65535} is 0, 162, 255. The simplest way to get from an 8-bit value to a 16-bit one is to multiply it by 257. So if you know your RGB value in its 8-bit form, you can also write the if condition like this:
set {r, g, b} to pick color at centerOfCurrentLayer
if {r, g, b} = {0 * 257, 162 * 257, 255 * 257} then
Finally, if certain layers that you need to pick are behind certain other layers, you'd need to adapt the script to hide and show each layer before picking its color. So the final script would look like this:
tell application "Pixelmator Pro"
	tell the front document
		set visible of every layer to false
		repeat with a from 1 to number of layers
			set visible of layer a to true
			set {x, y} to position of layer a
			set {w, h} to {width, height} of layer a
			set centerOfCurrentLayer to {x + (w / 2), y + (h / 2)}
			set {r, g, b} to pick color at centerOfCurrentLayer
			if {r, g, b} = {0 * 257, 162 * 257, 255 * 257} then
				load selection of layer a mode add selection
			end if
			set visible of layer a to false
		end repeat
		set visible of every layer to true
	end tell
end tell
Hope that helps!
User avatar

2020-10-10 04:55:46

Awesome! You guys go above and beyond. Thanks so much.
User avatar

2020-10-15 21:34:28

I can't seem to guess AppleScript's syntax. I'm trying to use the pattern fill effect command. I've tried various iterations of property formats. This is what I have:

tell application "Pixelmator Pro"

set theDocument to front document

make new pattern fill effect at the beginning of layers of the front document with properties {file:(path to desktop as text) ¬
"My_Doc.jpg", position:0, scale:100, angle:90, opacity:100, blend mode:normal}

end tell

Also, do the property inputs change if you use shape layers?

On another note, is it possible to deselect an item, layer or document? The select command works fine, but I haven't been able to deselect.

tell the front document to select item 1 of layer 1

tell the front document to deselect item 1 of layer 1
User avatar

2020-10-16 08:57:28

So, there are a few things that need to be addressed in your script. Let's start from the beginning:
tell application "Pixelmator Pro"
	set theDocument to front document
This is all fine, although you create a 'theDocument' variable to refer to the front document, but you don't use it later on and just say "the front document". So the variable is unused and we can delete it. Next:
make new pattern fill effect at the beginning of layers of the front document
You're telling Pixelmator Pro to insert a new effect object as the first layer in the front document. The trouble with that is effects aren't layers — effects belong to individual layers and layers belong to documents (this is covered in our AppleScript tutorial).

So what you actually need to do when creating an effect is specify which layer the effects belong to (just like when using the app). Here's what that would look like if we wanted to apply the effect to the first layer of the front document (I've also included some syntactic variations):
make new pattern fill effect at the beginning of effects of layer 1 of the front document
tell the front document to make new pattern fill effect at the beginning of effects of layer 1
tell the front document to tell layer 1 to make new pattern fill effect at the beginning of effects
tell layer 1 of the front document to make new pattern fill effect at the beginning of effects
Each one of those will work.

By the way, when I started out with AppleScript, nested tell blocks made this easier to understand because you can easily start from the top object and navigate down the hierarchy:
tell the front document
	tell layer 1
		make new pattern fill effect at the beginning of effects
	end tell
end tell
Let's keep going. In AppleScript, the ampersand '&' is used to concatenate strings. In your current script, you've inserted the symbol used to add line breaks '¬'. So, here's the correct string path:
(path to desktop as text) & "My_Doc.jpg"
Now, the next thing, the properties of the pattern fill effect. You have:
{file:(path to desktop as text) & "My_Doc.jpg", position:0, scale:100, angle:90, opacity:100, blend mode:normal}
That's file, position, scale, angle, opacity, and blend mode. Whenever you get stuck with AppleScript syntax, I'd suggest checking the Pixelmator Pro dictionary for the properties a certain command takes and the kinds of values that you can pass to those properties. If we check the AS dictionary for the properties of the pattern fill effect, these are image, position, scale, angle, opacity, and blend mode. So the first property is incorrect and the properties should, so far, look like this:
{image:(path to desktop as text) & "My_Doc.jpg", position:0, scale:100, angle:90, opacity:100, blend mode:normal}
Now, let's check the values we're passing to each property. In the first property, we're passing a string to a property that takes a file. That isn't always a problem but it can be, so to be on the safe side, I'd try and pass it an alias/file. I will admit this part of AS (i.e. when to use files/when to use aliases/sandboxing) is a bit of a mystery to me, but hey, if it says file, let's try to give it one. That would be:
(path to desktop as text) & "My_Doc.jpg" as alias
The next property is position. If we check the dictionary, we can see the value position takes is 'point'. This one is tricky because searching for "AppleScript point" doesn't give us much info. Point isn't really a basic data type, it's just a list of two integer values (the x and y coordinates) and lists are given between curly braces – {}. Position in Pixelmator Pro is measured from the top left corner, so {0,0} is the top left corner of the image. So {0,0} will put the top left corner of a layer in the top left corner of the image. Effects are actually a little different and they are positioned according to their center, so putting the effect at {0,0} will put the center of the effect in the top left corner of the image. In any case, the value should be in the form {integer, integer}. That means now, the script should look like this:
tell application "Pixelmator Pro"
	make new pattern fill effect at the beginning of effects of layer 1 of the front document with properties {image:(path to desktop as text) & "My_Doc.jpg" as alias, position:{0, 0}, scale:100, angle:90, opacity:100, blend mode:normal}
end tell
And, finally, running this script should work just fine.
by Binski 2020-10-15 18:34:28 Also, do the property inputs change if you use shape layers?
If you mean does the pattern fill effect take different properties for different kinds of layers, then no, it does not.
by Binski 2020-10-15 18:34:28 On another note, is it possible to deselect an item, layer or document? The select command works fine, but I haven't been able to deselect.
Just like in the app, one layer must always be selected. Is there a particular reason you'd like to have no layers selected? Also, are you by any chance confusing selecting layers in the Layers sidebar with making selections using the selection tools? Because there is a deselect command, but that is used to clear any active selections in the image (indicated by the marching ants).

Also, one last thing:
tell the front document to select item 1 of layer 1
The phrase 'item x' is used to refer to items in lists. So right now you're telling Pixelmator Pro to select the first item in the 'layer 1' list. But layer 1 isn't a list, it's a layer object. So you can just say "tell the front document to select layer 1". In theory, you could also say "tell the front document to select item 1 of layers" to do the same thing, because 'layers' is a list of layers. But that's obviously a more complex way of doing things.

P.S. On the forum, you can wrap AS code in the following tag to have it appear nicely formatted (you'd need to remove the spaces between the words apple and script, I included those because otherwise, the tags would start doing their job):
[apple script] 
--code
[/apple script]
User avatar

2020-10-16 20:14:49

Andrius-

Thank you again. You are prompt, thorough and notice the details! I think my biggest problem is that I'm hasty and sloppy. I appreciate your time and help.
User avatar

2020-10-16 23:42:51

Time for a scripts gallery?
User avatar

2020-10-17 10:50:58

by Teelar 2020-10-16 20:42:51 Time for a scripts gallery?
Possibly! The collection is certainly growing...