godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.12k stars 76 forks source link

Add more configuration options to shadows and borders in StyleBoxFlat #4948

Open ffernn-dev opened 2 years ago

ffernn-dev commented 2 years ago

Describe the project you are working on

A UI application which I'm trying to make a modern UI for.

Describe the problem or limitation you are having in your project

There seems to be some limitation in box shadows and borders in StyleBoxFlats. This is solvable with shaders but it would be nice to see a few more options in the editor, for both performance reasons and ease of use.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

  1. Make the blur amount on shadows customisable, seperate to the size of the shadow. At the moment, the only option for controlling the blur of the shadow is the size slider, there is no way to change the blur and size of the shadow separately. I'm proposing a system similar to how CSS handles box shadows (I think) where you first have a "spread amount", which basically controls the size of the shadow relative to the element, and a "blur radius", which controls a blur effect applied afterwards.

  2. This one might be a long shot but multiple/inner shadows. Again, referencing CSS, you can stack any number of box shadows with differing colours and sizes, which can create some really cool effects and is super helpful for adding some flair to UI without having to write complex shaders. Additionally, shadows can be set as "inset", meaning that they're applied inside and on top of the element, rather than outside and behind.

  3. Lastly, some changes to borders. As mentioned in #4329, unrounded borders would be nice, but that's already it's own proposal. My suggestion is, in Illustrator, you can choose where you want your border to be: inside, outside, or centred. Basically this just allows more flexibility with borders. Outside renders the border with one edge on the edge of the element, and the other edge extruded out; Inside renders how Godot currently renders borders, with the border extruding in; and centre is halfway between the two, with half of the border outside the shape and half inside.

Sorry for this wall of text but I think these small changes would make UI design a whole lot easier and pretty.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

All of these changes can be properties of StyleBoxFlat. Not 100% sure how the multiple shadows would work, maybe an array of some kind? Possibly with an editor like the gradient editor so users don't have to dig through arrays. If any more clarification is needed I'm happy to make lil diagrams.

If this enhancement will not be used often, can it be worked around with a few lines of script?

I think it will be used often, but if not it still can be done with shaders. It's just a little more complicated. If I do end up making shaders to do these I will post them here.

Is there a reason why this should be core and not an add-on in the asset library?

It changes core functionality of StyleBoxFlats.

YuriSizov commented 2 years ago

That all sounds reasonable. Although I feel that abusing multiple shadows is going to be expensive, as that just adds layers of extra steps to the internal shader. I've seen this trick being used and promoted for web apps, but it wouldn't surprise me if people who suggest using it don't think about lower-end devices and rock last year Macbooks themselves 😛

Calinou commented 2 years ago

My issue with exposing multiple shadows is that it makes the already lengthy StyleBoxFlat inspector even more lengthy. I'd prefer if we could find a way to automatically make the shadows more appealing, e.g. by using a non-linear gradient for the shadow edges.

As for specifying where the outline is drawn, have you tried using the content margin/expand margin properties to add some inner/outer padding to the StyleBoxFlat? I'd also prefer avoiding adding more properties if we can help it. While specifying where an outline is drawn is important when drawing SVGs, I've never felt a need to specify this explicitly in UI design.

Inset shadows sound difficult to implement without using actual clipping while drawing (which is complex). I also don't see them used nearly as often in web design lately (compared to 2012-2014).

ffernn-dev commented 2 years ago

Although I feel that abusing multiple shadows is going to be expensive, as that just adds layers of extra steps to the internal shader.

Yeah that's a good point. As I said that was a bit of a stretch

e.g. by using a non-linear gradient for the shadow edges.

Ah are the shadows drawn using a gradient at the moment? It'd probably be even easier to implement point 1 then

As for inset shadows, the reason I brought them up because I wanted to try my hand at Neumorphism in godot, to see if it was possible. I agree that that would be basically the only big use case.

Calinou commented 2 years ago

Ah are the shadows drawn using a gradient at the moment? It'd probably be even easier to implement point 1 then

Shadows aren't drawn using a gradient – they use a procedurally generated mesh with per-vertex colors. Drawing a custom gradient will require adding more points to this mesh, making it slower to render. Therefore, this would need to be optional.

Koyper commented 1 year ago

Here's another possible approach that creates attractive shadows at a low cost: create a new resource type called DropShadow that procedurally generates a CompressedTexture2D with blur, size and offset, and taylored to work with a NinePatchRect. This resource could them be shared with multiple Controls, like ButtonGroup, etc.

Maybe a ShadowContainer would then have the internal MarginContainer and NinePatchRect nodes, then render behind the child of the container. These could then be stacked as desired - the redish shadow in the image has a stack of two shadows. Alternatively, the DropShadow resource could go into StyleBox, and the NinePatchRect would be internally added if needed.

Screen Shot 2023-04-10 at 8 23 33 PM