Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StyleBox improvements to enlarge creative possiblities #6812

Open
davthedev opened this issue May 4, 2023 · 4 comments
Open

StyleBox improvements to enlarge creative possiblities #6812

davthedev opened this issue May 4, 2023 · 4 comments

Comments

@davthedev
Copy link

davthedev commented May 4, 2023

Describe the project you are working on

A game with some more intensive use of UI controls, such as panels, buttons, lists... I would like to give it a nice futuristic theme and be able to swap it easily later because I can reuse it in different contexts. Like rebranding a while-label app for a different client; I would like to do it with minimal work.

Ideally, by swapping out the theme and associated StyleBoxes, it can be done. But some graphic styles that I would like to achieve require making specific control classes or layering some together for the only purpose of styling.

I prefer delegating the styling as much as possible to the theme, in a similar fashion as CSS was invented to separate content and presentation for the web.

So, I started tinkering with the StyleBox classes to see what can be done, and judged the findings interesting enough to propose an improvement.

Describe the problem or limitation you are having in your project

The current StyleBox system has some limitations. We can make 9-patch textures or solid color frames.

I would like to be able to make:

  • Border gradients New styles for StyleBoxFlat: simple gradients, bevel effect... #6910
  • Beveled borders for buttons
  • Textured backgrounds with positioning parameters and clipping such as rounded corners
  • Adaptative box graphics that evolve with the dimensions, like responsive design in web development, beyond what is handled by the 9-patch system

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

Improvement of the current StyleBox classes, while taking care of maintaining compatibility and performance. New types of StyleBoxes would be added.

By combining the new elements, I can widen the theming possibilities without requiring any changes to the Control nodes.
Anywhere there is a StyleBox resource used for drawing, those possibilities are available.

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

The idea is being worked on; I will soon put a link to the functioning prototype and some screenshots.

StyleBoxFlat

The current StyleBoxFlat is changed to support simple gradients and bevel effects on the border.

I have a functioning prototype with similar polygon budget as the current StyleBoxFlat.
Under the hood, StyleBoxFlat draws a ring of GL triangles. By adjusting the colors of the vertices, I can get bevels, simple 2-color gradients and per-border color customizations working. And it gives cool results.

There are some presets (solid, gradient, bevel/inset) and you can override the color of each one of the four sides.

Examples from the current implementation:

image
A bevel effect

image
A horizontal gradient border. No texture involved!

image
A 4-corner, 2d gradient border. No texture either!

imageimageimage
Same box with different combinations of parameters:

  • Smooth or sharp border color corner joints
  • Combining with the existing blend effect for a smooth button appearance

New types of StyleBox are added.

StyleBoxStack

Work in progress; basic prototype is functioning

It is a way to stack multiple StyleBoxes in one.
In a control, anywhere there is a StyleBox resource, you can draw a stack of multiple ones. The StyleBoxStack resource references an array of other StyleBox resources that act as the different layers.

Each layer can have a different margin and some positioning hints.
Those hints includes telling the layer to either take the full space, or a fixed width while being centered for instance.
Each layer can have a condition based on size to be shown or hidden. The resulting graphic can dynamically evolve according tho the size of the box being drawn, with some extra detail that can be shown at larger sizes for example.

The effects you can achieve with this approach are interesting, such as:

  • Double borders
  • Bevel over a texture
  • Texture + solid border
  • Drop shadow beyond what is permitted by StyleBoxFlat
  • A futuristic frame that shows more complex details on larger dimensions, and simplifies its drawing automatically in smaller dimensions
  • Toggle button with the indicator light built-in, anchored to a corner

Here are some results of the current implementation:

image
A button with a double border, made of two StyleBoxFlat with gradients

image
A beveled button. On the background, a StyleBoxTexture with a 2D gradient texture, layered with a StyleBoxFlat with distinct border colors for the bevel effect.

StyleBoxSimpleTexture

The name can be changed. This is to distinguish from the current StyleBoxTexture which I would rather call a "StyleBoxNinePatchTexture".
The StyleBoxSimpleTexture would behave a bit more like the TextureRect, allowing adjustements of the texture to keep it centered or anchored to a side or corner, contain or cover, preserve aspect ratio or not... The image would be clippable using simple shapes such as a rounded rectangle or a circle. Perhaps, an advanced clipping path would be editable.

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

Creating graphics for the purpose and importing them as 9-patch can be a solution. Another possibility is to code specific controls for the purpose by layering the necessary nodes. But it lacks reusability and requires a round-trip to the graphics software just to try out different color schemes.

Hooking into the StyleBox system offers the new design possibilities to all Control nodes that use style boxes for their elements. This includes the highlight frame for the currently selected list item, for example.

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

The StyleBox system is tied up to the core and not easily extendable using a plug-in. StyleBox-derived class type checks are hardcoded in multiple places, for instance.
The proposed additions keep in mind that we do not want to bloat the engine. I have tested on StyleBoxFlat that we can have some nice improvements without impacting performance.

In addition, theme creators would benefit from the additions and those would be usable directly inside the editor!

@dalexeev
Copy link
Member

dalexeev commented May 5, 2023

The StyleBox system is tied up to the core and not easily extendable using a plug-in.

There are StyleBox virtual methods that you can override:

Example:

@tool
extends StyleBox
class_name MyStyleBox

@export var tile := false:
    set(value):
        tile = value
        emit_changed()

@export var modulate := Color.WHITE:
    set(value):
        modulate = value
        emit_changed()

var _icon := preload("res://icon.svg").get_rid()

func _draw(to_canvas_item: RID, rect: Rect2) -> void:
    RenderingServer.canvas_item_add_texture_rect(to_canvas_item, rect, _icon, tile, modulate)

@Calinou
Copy link
Member

Calinou commented May 9, 2023

Does this proposal support StyleBoxFlats with a background gradient, rounded corners and no visible borders? See #6846.

@davthedev
Copy link
Author

I am working on it to check feasibility at the moment. This is really something I would like to make possible.

In the stable version, the best bet is to use a GradientTexture2D over a StyleBoxTexture. But you cannot have the rounded corners at the same time.
Thought about a different kind of StyleBox where you can apply any texture, working the same way as the TextureRect control, and have some clipping too in the form of rounded corners or different shapes. We can also add texture support to StyleBoxFlat as an option.

@davthedev
Copy link
Author

Gradients feasibility is confirmed!
At least for the simple ones: 2-point and horizontal / vertical only for now.
Implemented: godotengine/godot#77215

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants