godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.08k stars 69 forks source link

Tiled Progress Control node #474

Open PKGaspi opened 4 years ago

PKGaspi commented 4 years ago

Describe the project you are working on: I'm working on a Mega Man themed game. The energy bars (for hp and weapon ammo) used in the original games are tiled, with small cells representing each remaining point.

Describe the problem or limitation you are having in your project: As of v3.2 there are 2 nodes for bars of this type: ProgressBar and TextureProgress. TextureProgress allows to use a texture, which could be a group of the tiles that are going to be used, but this solution doesn't scale very well, as you could have enemies with different hp values. This node has an option to use a NinePathRect, which for some reason can't be tiled like the dedicated node. Adding that option would be enough to implement a TiledProgress bar.

Describe the feature / enhancement and how it helps to overcome the problem or limitation: As said, having a dedicated node for TiledProgress or an option to tile a TextureProgress would be the easiest way to implement this kind of feature on a project like mine.

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams: My suggested solution is to support tiled Nine Path Rect in the TextureProgress node. I've taken a look to the code for this particular node at texture_progress.cpp and it looks like it has it's own implementation for drawing the NinePathRect. I'm sure there is a reason to not use the same implementation used in the dedicated NinePathRect node.

If this enhancement will not be used often, can it be worked around with a few lines of script?: The best workaround I can think of is creating a custom Control node with this behaviour. A NinePathRect which is only drawn a percentage of it.

Is there a reason why this should be core and not an add-on in the asset library?: This type of progress bar can be very useful, especially when creating retro-like games. Beginners and new users may aim for a game like this to learn to use the engine and not finding a node that does this for them may not be the most appealing.

willnationsdev commented 4 years ago

As said, having a dedicated node for TiledProgress or an option to tile a TextureProgress would be the easiest way to implement this kind of feature

Between the two options, I think it would be better to simply add a tiling effect to the texture rendered by the TextureProgress (option 2). There isn't enough difference in the suggested features to justify creating a whole new node class imo.

hsandt commented 4 months ago

I was also about to suggest adding parameters to TextureProgressBar to match NinePatchRect, namely Axis Stretch > Horizontal and Vertical so user can set them to Tile or Tile Fit instead of Stretch (which TextureProgressBar always uses).

Note: TextureProgress seems to be the name in Godot 3

Since there are Textures for Under, Over and Progress, we'd need 3 sets of Axis Stretch parameters though, to be able to customize them independently.

I also found this issue which takes things at an even lower level and suggests supporting 9-patch on every texture: https://github.com/godotengine/godot-proposals/issues/3562 (a bit like Unity sprite 9-slicing at import level I suppose)

This would also fix the issue and avoid adding extra parameters for 9-patch on every rendering node using a texture, and in this case, on the 3 Textures used by TextureProgressBar. But also less likely to be implemented in the near future.

It seems that using NinePatchSprite with some custom code to set its size is the best way for now.

Unfortunately I don't see how to reuse TextureProgressBar and combine it with NinePatchSprite since it doesn't have a child "Filled Gauge" that would dynamically change size with progress, on which we could parent our NinePatchSprite with Full Rect anchors so it would auto stretch with progress... (Unity creates complex UI widgets that consist in a full hierarchy of elements, so you can use that trick in that engine, but it seems Godot is really about single, self-contained nodes) So we'd really need custom code.