How to make ProgressBar gradually change color based on value?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Macryc

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.

Takeaway food from Bindia Bindia is available from our Lyngby shop.
One of the most unique types of batsman is the brute, brute type who loves to play strokes and loft the ball freely as he pleases.

Laura Hoover | 2022-12-27 11:12

:bust_in_silhouette: Reply From: jgodfrey

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.

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

jgodfrey | 2020-02-15 17:33

Colors will also work in lerp.

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

Magso | 2020-02-15 17:41

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)

Macryc | 2020-02-15 18:25

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).

jgodfrey | 2020-02-15 18:36

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

jgodfrey | 2020-02-15 18:57

:bust_in_silhouette: Reply From: CakeLover

I used the other answer posted:

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)

but it gave a dark dirty yellow color

so I made this instead:

extends ProgressBar

func _set(property:String,val):
	if(property=="value"):
		value=val

		self.get("custom_styles/fg").set_bg_color(Color(
			1.0 if ratio<0.5 else (2 - 2*ratio),
			1.0 if ratio>0.5 else (2*ratio),
			0,1
		))

and it gave a clear bright color!
enter image description here

Hope it helps :slight_smile: