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

Add a TextureProgressBar3D node to represent linear and radial progress bars in 3D space #8430

Open
Calinou opened this issue Nov 14, 2023 · 1 comment

Comments

@Calinou
Copy link
Member

Calinou commented Nov 14, 2023

Describe the project you are working on

The Godot editor 🙂

Describe the problem or limitation you are having in your project

There is no easy way to draw a progress bar in 3D space. However, progress bars in 3D have many use cases:

  • Showing health bars above players or enemies, typically with linear progress bars.
  • Showing capture or construction progress meters above buildings. Depending on the kind of game, these tend to favor radial progress bars and are sometimes visible through walls.
  • Drawing diegetic UI that exists near the player.
  • Displaying human-readable numeric information above an object for debugging (or complement an existing Label3D doing so).
hp webp hp2 webp hp3 webp

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

Add a TextureProgressBar3D node to represent linear and radial progress bars in 3D space.

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

TextureProgressBar3D's implementation would be inspired by Label3D, which means it'd inherit from GeometryInstance3D (and not Sprite3D). Starting from the same code as Label3D is probably a good idea. This code can then be modified to generate a QuadMesh whose size changes depending on progress (for linear progress bars). For radial progress bars, a different implementation is needed.

The code that draws radial progress bars in TextureProgressBar can be used as a reference: https://github.com/godotengine/godot/blob/baf6b4634d08bc3e193a38b86e96945052002f64/scene/gui/texture_progress_bar.cpp#L487-L551


Question: Why not implement ProgressBar3D that uses styleboxes, or a full-blown Control3D UI system?

While these solutions would be more flexible, they have several issues:

  • While nine-patch (StyleBoxTexture) drawing could be made to work in 3D, StyleBoxFlat drawing is designed to work in 2D only (especially its antialiasing).
    • ProgressBar also doesn't support radial progress bars, which are fairly common in 3D UI.
  • A full-blown 3D control system would be extremely complex, requiring the reimplementation of mechanics like anchors to make sense in 3D space.

In contrast, TextureProgressBar3D is a small, self-contained implementation similar to Label3D. If you want to ensure progress bars remain crisp at a high resolution, design the texture for a resolution such as 4K and make sure mipmaps are enabled on the material so that it scales down to lower resolutions nicely.

When TextureProgressBar3D is coupled with the existing ability to draw 3D text and sprites, most use cases should be addressed quite well already. Full-blown UI interactions in a 3D world will remain feasible with the use of a Viewport, as shown in the GUI in 3D demo.

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

For linear progress bars, this can be worked around in two ways:

  • Use a Label3D node that prints vertical bar characters (such as |) to represent progress. This is less precise and slower as it requires more triangles that may result in overdraw (remember that Label3D is transparent). This is what the 3D Labels and Texts demo currently does.
  • Use a MeshInstance3D + QuadMesh setup with the X scale being changed depending on the progress value (UV1 scale can be adjusted to counteract texture stretching in this case). This is a complicated solution to put in practice, with a fair amount of scripting needed (and having to make materials in each progress bar unique so they don't affect each other).

There is no easy workaround for radial progress bars if you want a good level of precision. If you don't need a lot of precision, you could use a MeshInstance3D + QuadMesh setup with UV1 offset set to display one of N pregenerated texture slices. This solution requires a lot of memory if you use high-resolution textures and need a lot of progress steps for a smooth appearance.

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

This is about improving the 3D game development experience, as most polished projects will need to draw at least one progress bar in 3D space at some point in their development.

@des1redState
Copy link

This would be great. I'm currently attempting to add a progress bar to a 3D scene using a subviewport and Sprite3D but hitting some weird rendering issues.

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

2 participants