0 votes

Hi guys! What is the recommended approach to making the progress bar gradually re-color itself based on current value? Let's say, if value = 100 Fg color is green, if value <= 10 Fg color is red. Anything in between is a color on a gradient between green and red.

asked Feb 15 in Engine by Macryc (289 points)

1 Answer

0 votes

I'd probably use range_lerp to map the red and green components of the progress bar's color value to the appropriate ranges based on its current value.

So, something like this:

func _ready():
    $ProgressBar.value = 10
    var r = range_lerp($ProgressBar.value, 10, 100, 1, 0)
    var g = range_lerp($ProgressBar.value, 10, 100, 0, 1)
    var styleBox = $ProgressBar.get("custom_styles/fg")
    styleBox.bg_color = Color(r, g, 0)

That should smoothly map between red and green as the progress bar's value increases. However, mixing roughly equal parts of red and green in the middle of your range may not give you the color(s) you expect.

answered Feb 15 by jgodfrey (5,496 points)
edited Feb 15 by jgodfrey

Note, for the above, I assigned a new StyleBoxFlat to the the ProgressBar's Fg property, in the inspector.

That's done in the inspector at ProgressBar | Control | Custom Styles | Fg

Colors will also work in lerp.

color = lerp(red, green, ProgressBar.get_as_ratio())

thank you. I wanted ot try this method out but keep getting the invalid get index value error on these lines var r = range_lerp($ProgressBar.value, 10, 100, 1, 0)

Hmmm... I assume the issue is related to accessing your ProgressBar.value property.

In my case, my ProgressBar was just a direct child of the node containing the above script. So, I can reference it via $ProgressBar. If you're progress bar is positioned differently in the scene (and it likely is), you'll need to get access to it in whatever way makes sense.

If you can't figure it out, post a screenshot of your scene tree (or describe it).

Here's a more complete example, where you can drag a HorizontalSilder to set the value of the ProgressBar and see the color change accordingly. Don't forget to connect the on_value_changed signal of both controls to the below script.

extends CanvasLayer

onready var styleBox = $ProgressBar.get("custom_styles/fg")

func _ready():
    $HSlider.value = 50

func _on_HSlider_value_changed(value):
    $ProgressBar.value = value

func _on_ProgressBar_value_changed(value):
    var r = range_lerp(value, 10, 100, 1, 0)
    var g = range_lerp(value, 10, 100, 0, 1)
    styleBox.bg_color = Color(r, g, 0)

That works with the script attached to the top-level of a scene tree that looks like this:

Scene Tree

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.