godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
89.71k stars 20.82k forks source link

[ProgressBar] inconsistent Step behavior #93332

Open ivoiv opened 3 months ago

ivoiv commented 3 months ago

Tested versions

v4.2.2.stable.mono.official [15073afe3]

System information

Godot v4.2.2.stable.mono - Windows 10.0.22631 - GLES3 (Compatibility) - NVIDIA GeForce RTX 4090 (NVIDIA; 32.0.15.5585) - 12th Gen Intel(R) Core(TM) i5-12600K (16 Threads)

Issue description

When using the default Step of 0.01, ProgressBar will not increase(+=) Value by a value lower than or equal to 0.005 via script. It will however increase value by 0.006 and above.

If the logic is that ProgressBar won't accept values lower than it's step, it's inconsistent that it accepts 0.006+ but not 0.005-.

Setting Step to 0.009 makes it accept both values. It seems to me like a rounding error somewhere in Value's Set method.

I think it should either accept both or none. The current behaviour's inconsistency is very confusing and it took me hours to figure out why a specific Bar wasn't working.

Steps to reproduce

  1. Create a Progress bar.
  2. Attach new Script.
  3. In _Process increase the Progress Bar's value by 0.005 per tick.
  4. Nothing happens.
  5. Increase value to 0.006.
  6. Now it works.

Minimal reproduction project (MRP)

ProgressBarPrecision.zip

TNicoletti commented 3 months ago

It seems to me that it always increases when the value of the tick is at least greater than half the step, if we get the step to 0.005 it will increase for any value greater than 0.0025, for example 0.00251, but not for 0.00250. If we set the value of the step to 0.1, it will not increase for 0.05 for another example(but it gets stuck at 2% for some reason). A lot of the godot issues are rules that are there but are simply not written anywhere.

ivoiv commented 3 months ago

You're right, it does seem to accept values greater than half the step. I still doubt this is intended behavior, it just sounds very arbitrary. It should either respect the step as a hard limit or it should not.

I'm trying to find where it's happening but I don't have the repo locally and CPP isnt my first language.

It should be happening somewhere in Range as that's where ProgressBar inherits and there's a lot of clamping and rounding happening. There's a reference to some Ratio that isn't in the editor even tho it seems like it should. Calls some set_as_ratio https://github.com/godotengine/godot/blob/2b11d0ca966e93c621dccc57951ccbe2a0133251/scene/gui/range.cpp

I'll dig more tomorrow if I get time but I have a hunch it's a rounding thing as 0.006 is definitely closer to 0.01than it is to 0.00 whereas it maybe it floors 0.05down to 0 somehow..

dalexeev commented 3 months ago

step is used to round the value to the nearest multiple of the step (shifted by min_value). Therefore, if you add/subtract less than 0.5 * step, the value remains unchanged, since it is rounded to the original value.

The value and the displayed value are the same. If you want to have an implicit unsnapped value that is different from the displayed value (and the value), then you should create a separate variable.