Layer styles that apply to groups

What features would you like to see in Pixelmator Pro?
User avatar

2020-07-10 20:28:01

Would it be possible to add a means of applying layer styles to layer groups as well? For example, in Photoshop you can add layer effects such as stroke, drop shadow, etc. to a layer group and it'll apply to the composited result of all of the layers in the group, which works better for a lot of things than applying the effect individually to each layer within the group (for example, it lets them all cast a single unified drop shadow).

Individual layers seem to have all of the style components I care about but groups as a whole do not, and the style "add" button is disabled.
User avatar

2020-07-13 14:30:34

We'd like to add this for sure but the stroke layer style currently makes this quite difficult — we'll see what we can do!
User avatar

2020-07-13 14:41:12

Ah, thanks for responding. I'm a bit surprised that any of the effects would make it difficult, since at least intuitively it seems like anything that can work on a single layer could also work on the composited result of multiple other layers, but I can imagine there's probably something tricky in the compositing pipeline I'm not considering especially if it only involves one effect and not the others.

I used to do graphics programming as my main line of work and I know how weird stuff can get, especially with alpha blending.
User avatar

2020-07-13 14:52:09

Yep, I'm not an expert here but as far as I've spoken to the devs about this before, it would require a relatively significant amount of effort (relative to the significance of the feature itself) mainly due to the computational costs of the stroke layer style.
User avatar

2020-07-13 15:25:14

Yeah, I can see the stroke effect being pretty difficult to make efficient, since it's not a 1:1 pixel mapping thing. Still, I don't see why it would be any more difficult to do on a composited layer group than on a single layer. But I obviously don't know enough about how Pixelmator works internally and I know how annoying an armchair developer can be.
User avatar

2020-07-14 09:01:01

So I decided to follow up on this (because, intuitively, I agree it shouldn't be difficult) and the problem is more about performance rather than programming difficulty. Basically, the stroke layer style requires a lot of processing and, while applying it to a group is simple enough, let's say you move one of the layers inside a complex group — instantly updating that stroke will significantly impact performance. Of course, you can also render the changes once the layer has stopped moving, but that usually confuses users and can tend to look buggy, so it's not an ideal option. Having said that, we've made some performance improvements to strokes over the past six months or so, so getting the kind of performance we'd be happy with might be possible with some further optimizations and it looks like group layer styles are now in our plans.
User avatar

2020-07-14 13:48:09

Ah! Yes that makes a lot of sense. Thanks for taking the time to explain.

I think users would be fine with a brief pause in that rare case but I do appreciate how responsive Pixelnator strives to always be.
User avatar

2020-10-27 06:05:26

I know I'd be okay with the performance hit in exchange for being able to non-destructively group and apply layer styles. I have a frequent need for vector objects with different fills but a unified stroke.
User avatar

2020-10-27 15:47:01

by Lee Davis 2020-10-27 04:05:26 I know I'd be okay with the performance hit in exchange for being able to non-destructively group and apply layer styles. I have a frequent need for vector objects with different fills but a unified stroke.
Obviously, when you know something is computationally difficult, you can make your peace with a performance hit, but it's a big no-no because most users won't be aware of this and will just be frustrated by the experience. But the good news is that we should eventually be able to add this.
User avatar

2020-10-27 17:34:50

So, one thing that I've been wondering about, since this thread has become active again: Right now you can apply a complex layer style to individual layers, and then composite them together. I know from experience as a graphics programmer that compositing layers is a fairly cheap operation, while applying outlines is a much slower operation.

Let's say for the sake of argument that applying an outline to a layer takes 5 times as much time as it takes to composite 5 layers together, and we're trying to apply an outline to a group of 5 layers. So, we can say that the compositing operation takes 1 unit of time, and an outline takes 5 units of time.

Applying the outline separately and then compositing the results together would then take 26 units of time (5*5 outline + 1 composite). However, compositing first and then applying the outline would only take 6 units of time (1 composite + 1*5 outline).

Obviously this 6 units of time would have to happen every time any of the component layers gets updated, but that's also the case with the current situation, as it takes 6 units of time to update each of the individual layers (since you have to re-apply the outline and then re-composite).

And this is how it will be regardless of what the time difference is, and intuitively it seems like it should be the same regardless of the complexity of nesting.

So, how is it worse for performance to support styles on layer groups?
User avatar

2020-10-27 21:42:52

The way I will do it...

Every layer will have unique name... I would move this to the group name...
When I will use AppleScript to select the names of the layers in he group.

Apply the new style... to every layers in the group.

The problem you may face is... Pixelmator Pro store layer with a index... so how would it be possible to select a name with AppleScript.

With a handler of this you could... tell AppleScript to select layer name and the function will convert the name to index number.
From this you could select any layer and apply any style you want... also inside group layer.
on list_position(this_item, this_list)
	repeat with i from 1 to the count of this_list
		if item i of this_list is in this_item then return i
	end repeat
	return 0
end list_position
User avatar

2020-10-28 12:58:21

by fluffy So, one thing that I've been wondering about, since this thread has become active again: Right now you can apply a complex layer style to individual layers, and then composite them together. I know from experience as a graphics programmer that compositing layers is a fairly cheap operation, while applying outlines is a much slower operation.

Let's say for the sake of argument that applying an outline to a layer takes 5 times as much time as it takes to composite 5 layers together, and we're trying to apply an outline to a group of 5 layers. So, we can say that the compositing operation takes 1 unit of time, and an outline takes 5 units of time.

Applying the outline separately and then compositing the results together would then take 26 units of time (5*5 outline + 1 composite). However, compositing first and then applying the outline would only take 6 units of time (1 composite + 1*5 outline).

Obviously this 6 units of time would have to happen every time any of the component layers gets updated, but that's also the case with the current situation, as it takes 6 units of time to update each of the individual layers (since you have to re-apply the outline and then re-composite).

And this is how it will be regardless of what the time difference is, and intuitively it seems like it should be the same regardless of the complexity of nesting.

So, how is it worse for performance to support styles on layer groups?
Two things — one, I'm not a programmer, so when the programmers explain stuff to me and I try and pass the knowledge on, it's possible I'll miss out important details or emphasize the wrong things. Two, even though I do roughly understand the technical side of rendering, my knowledge isn't especially deep, so I can get things wrong because of that, too. Let me try one more time to explain how I understand the issue:

Just like in your example, let's say that when you add a stroke to a single layer, rendering the layer in isolation takes 1 unit of time, and rendering the stroke takes 5 units of time. Now let's say you resize that layer, each time the stroke must be recalculated for the new layer outline, it takes 6 units of time, which is short enough so that there is no delay as you resize it and everything works smoothly in real-time.

Now let's imagine you have a group with 10 layers. You apply a stroke to it. For the sake of argument, compositing those layers with each other when all their blending modes are set to Normal takes 10 units of time (I think you must also composite it with the rest of the image, but we'll ignore that). Adding a stroke adds another 5 units. Maybe our imaginary 15 units of time is just enough to apply the stroke quickly enough so that everything happens almost in real-time, at least with no perceptible delay.

But now let's say certain layers have different blending modes so it will take longer to blend them together before you can trace them. Applying the stroke is trivial enough still, a little bit slower, but it's OK. The problems will happen each time you move a layer inside the group, which means the entire group must be blended again as the layer changes position in the group. And then its outline must be traced to render the stroke, which will take long enough so that there will either be lag and the stroke will only update once you stop moving the layer. Or the layer will stutter as you move it into position in order to render the stroke accurately each frame.

When moving objects in complex documents, as far as I know, only a specific area of the image is rendered, but for an accurate stroke, the entire group has to be composited and then traced. Of course, there won't be problems with simple groups but we need to ensure performance is great no matter the document so we need to figure out clever ways to get around this slowness. Inaccurate rendering (i.e. updating the stroke only after the layers have stopped moving) is pretty much a big fat no as that's not acceptable to us from a UX perspective. Again, it isn't necessarily impossible to find ways to add this while having good performance, but the decision is — do we allocate a month or two (possibly even more) of dev time to this one improvement that may still be unacceptably slow in certain workflows and documents, or do we work on something else.

Disclaimer: Everything stated above may be completely and categorically wrong. (this is to save me embarrassment when someone actually knowledgeable comes along and contradicts everything I've said)