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

Spin slider: More flexibility for manual float input regardless of range parameters #3524

Open
akien-mga opened this issue May 29, 2018 · 12 comments

Comments

@akien-mga
Copy link
Member

Context

We have many issues relative to the inspector spin slider, which often constraints the values which can be selected both via the slider/spinbox and via manual input (typing the value).

The range and step of the slider/spinbox are defined via PROPERTY_HINT_RANGE (linear) and PROPERTY_HINT_EXP_RANGE (exponential), which take the following hint parameter: "min,max,step" e.g. "0.01,100,0.01".

This works fine and usually the ranges specified cover the majority of use cases, or, more importantly, prevent the input of some invalid values (e.g. some properties can't take negative values, or 0, or too high values would crash the editor and/or the game).

The issue

But in a non-negligible percentage of use cases, users still need to be able to set values which are:

  1. Below the min that we defined
  2. Above the max that we defined
  3. With more precision than the step we defined allows

In the master branch (with dfd133169), @reduz recently added support two hinting options or_greater and or_lesser which solve the points 1) and 2) above when defined manually, e.g. "0.01,100,0.01,or_greater" would allow manual input from 0.01 included to MAX_FLOAT, but the slider itself would only go up to 100.

The remaining problems are, IMO:

  • We still need a way to allow more precision when needed, see e.g. CircleShape2D radius can only increase/decrease in steps of .5 godot#9219, so a third option like or_finer or or_more_decimals would be needed.
  • I think that adding such options to each range hint is quite bothersome, and I posit that the majority of number input fields would benefit from allowing more input freedom by default. As such, I think it might be better to change the system to my following proposal.

The proposal

Instead of using the same limitations for the slider/spinbox and for manual input, I propose to decouple the two and allow free input by default in the input box (so the or_greater and or_lesser options could be removed, and the third option for more precision would not be necessary).

This means that by default, a PROPERTY_HINT_RANGE with "0.01,100,0.01" would:

  • Let you input -3.08, 142 and 0.0005 manually (it would stop rounding your input to whatever it deems appropriate)
  • Limit the values you can set via the slider/spinbox to the specified range. So if you input -3.08, the slider would be at its min position, and if you click it to slide the value, it would jump to 0.01 (the actual slider min) and then go up in increments of 0.01.

Then we could add options to restrict values for the properties where negative values don't make sense, where 0 must be excluded, or where the range's min or max should be enforced, e.g.: no_negative, no_zero, use_min, use_max.

It's still a similar system to the existing one, but I think that "free input by default" would be better than "restricted by default".

Other proposal

Another solution could be to fully decouple the hint range used by the slider/spinbox (which should be the "common usage" value) and the enforced range of the manual input, by allowing to customize both.

For example, one could set a slider/spinbox range to "0.01,100,0.01", and a manual input range to "0.0001,inf,0.0001", meaning that you could manually input values from 0.0001 to MAX_FLOAT with a precision of 4 decimal digits.

It could be specified maybe as two arguments: PROPERTY_HINT_RANGE, "0.01,100,0.01", "0.0001,inf,0.0001".

WDYT? Even as I write this wall of text I'm thinking that my two proposals might not be so much better than the current state, and that it might be simpler and good enough to implement an or_fine or or_more_decimals option, but I'd be interested in more opinions.

@Bauxitedev
Copy link

Going to agree with the first proposal. There's an uncountable number of sliders which are restricting me right now, off the top of my head:

  • Proximity fade distance needs to allow <0.1 (yet >0)
  • Sphere/cylinder/capsule mesh subdivisions needs to allow >100
  • Pretty much all particle velocity sliders are arbitrarily clamped to 100, which is really fast in 3D but in 2D it's only 100 pixels per second.
  • Light intensity needs to allow >16
  • Emission intensity needs to allow >16
  • Etc

@groud
Copy link
Member

groud commented May 29, 2018

Shouldn't we consider finding a way to have several hints ? Since the inspector is going to be more flexible that might be needed. But that might be too much I don't know...

@toger5
Copy link

toger5 commented May 31, 2018

I think this is really needed.
Some sliders are really annoying to use because it uses absolut max/minimums. Geavity for exmple is between -4048,+4048 this 8k range makes it unusable with the slider. Also some angles are bigger (for animations) but rhe sliders fel awkward because of that.

I also prefer solution 1.
Adding more hints.

@xemjeff
Copy link

xemjeff commented Jun 3, 2018

I have recently had to adjust the slider hints for the physics hinge_constraint, which sets a practical range of [-200,200] but allows user entry outside the range with hints or_lesser, or_greater.(godotengine/godot#19246)

I prefer the proposal idea of adding the hint or_finer, which is consistent with the other hints I have used.

Calinou referenced this issue in Calinou/godot Jun 16, 2019
@akien-mga
Copy link
Member Author

See godotengine/godot#18251 and godotengine/godot#25470 for some more context and discussion on what should be implemented ideally.

godotengine/godot#30776 made the default float step configurable, but it doesn't solve the need to decouple spin/slider step from the decimal points that can be input and visualized in the inspector.

myhalibobo referenced this issue in myhalibobo/godot Sep 3, 2019
@Calinou
Copy link
Member

Calinou commented May 11, 2020

Should we remove the hardcoded float step from most properties and only include it where it's absolutely required to not break things? This issue popped up again today on the Godot Q&A: https://godotengine.org/qa/70018/why-does-the-inspector-ui-truncate-numbers-to-decimal-places

This way, the Default Float Step setting would be much more useful, and we'd spend less time reasoning about the float step for every property.

@akien-mga akien-mga transferred this issue from godotengine/godot Nov 10, 2021
@akien-mga
Copy link
Member Author

Transferred this from the main Godot repo, so the OP doesn't follow the usual template (but is still fairly close in spirit).

AFAIK this is still relevant, but could warrant more discussion.

@akien-mga
Copy link
Member Author

We discussed this in a proposal review meeting, and agree that adding a way to manually input more precise numbers while still being able to use a low-precision slider step would be useful.

Our current consensus would be to experiment with something like this:

  • Only perform snapping when using the slider / spinbox, so manual input can still use more decimals.
  • The default precision allowed for manual input then becomes the one configured by the Editor Setting interface/inspector/default_float_step (defaults to 0.001).
    • This also affects the display of the values saved in the scene, they would no longer be snapped to the spin slider step by default.
  • A snap hint could be added for cases where we want to force snapping to the spin slider step even for manual input
    • For this we should review existing properties with range hints to see which ones would actually benefit from something like this.

@akien-mga akien-mga moved this from Ready for Review to Ready for Implementation in Godot Proposal Metaverse Jun 30, 2022
@timothyqiu
Copy link
Member

timothyqiu commented Nov 12, 2022

A snap hint could be added for cases where we want to force snapping to the spin slider step even for manual input

I think this hint is redundant: If it's absolutely necessary to force a precision, we have to do snapping in the property setter too. But when the setter snaps value, the slider won't need to do anything special anymore.


Since manual input allows arbitrary value, I think the slider / spinbox can also produce arbitrary value by default, and snap only when asked to (e.g. when holding CTRL).

Float steps used in the engine are all specified in 10^n, i.e. they're values like 0.1 and 0.01, not values like 0.8 and 0.73. If we drop support for arbitrary step, I think a suitable step can be figured out by code based on the value range. For example, a range of 0-1 can snap to 0.1 by default, and a range of 0-10 can snap to 1.0 by default. For more precision, holding SHIFT makes a range of 0-1 snap to 0.01, and a range of 0-10 snap to 0.1.

Currently, dragging the slider box is the same as dragging the slider handle. I think it'll be handy if we only snap the delta produced by dragging the slider box itself. For example, if the slider decides to use 0.1 as its step and its current value is 0.123, dragging the slider handle produces values like 0.2, 0.3, and 0.0, while dragging the slider box can produce values like 0.223, 0.323, and 0.023.

@RicardRC
Copy link

RicardRC commented Jun 1, 2024

For my use case, I don't care about sliders. I just need to enter values like 6.67430e-11 into an exported variable, and have it behave just like if I declared var value: float = 6.67430e-11 in a script. I know it might lose precision, but floating values are designed to be able to keep some precision at an arbitrary mantissa. Seeing that this issue is about six years old and there seems to be no solution in sight, how about a simple tag that disables all forms of spinner or drag edition of an inspector float and simply allows one exported variable to be respected as much as a variable declared in a script? Thank you!

image
This image shows that values enterd by constant or var in gdscript work fine. But in this case, Orbital Inclination had the same value enterd by pasting the value into the inspector on the right, and even though the inspector keeps the value ok after specifying the range to be of precision 0.0, it gets ignored anyways, and results in a multiplication by zero that defeats the purpose altogether.

@MrEgggga
Copy link

MrEgggga commented Jul 1, 2024

I've been working on implementing some form of this at https://github.com/MrEgggga/godot/tree/permissive-range, although it's together with something akin to godotengine/godot#88354. Some questions that have come up in my implementation:

  • How should values finer than the step size be displayed? I can see two possibilities:
    • Never truncate values -- show the whole thing at all times. This seems like the "canonical" solution, but it might look ugly due to rounding errors (see Parallax2D: Repeat size is getting value 2.08165e-12 instead 0 godot#91631 and below).
    • Truncate values to the step size, but show full values when editing. In my opinion this is nice (and would probably be the best for SpinBox / for usage in games and other applications), but it might be unintuitive for other people, and I could easily see constantly switching how numbers are displayed causing bugs (although I haven't run into any big ones with my implementation).
  • Many fields which are edited with EditorSpinSlider are not doubles, but real_ts and (C++) floats, which are both single-precision by default. If unrounded values are simply displayed using String::num with no limit on number of decimal places, this causes rounding errors and makes these fields significantly harder to edit. For example, if you enter 0.12345 into a component of a Vector3 (stored as real_t), the field displays as 0.12345000356436 instead. For my implementation I went with an ugly solution involving an extra field in EditorSpinSlider (and extra range hint) denoting whether the float is single- or double-precision and stringifying numbers with more or less precision depending on this field. (I talk about this in more detail here.) Another option is to limit precision to 6 decimal places regardless of how precise the float actually is (simple but kind of against the point of this whole proposal).
  • If finer input is allowed, it becomes possible to input smaller values, but we reach a limit at 5e-15 or so -- String::num() outputs 0 by default for any numbers lower than this. It would be possible to set fields lower than this, but it would be impossible to see that the value isn't actually 0 and clicking on and off of the EditorSpinSlider would actually set the value to 0 -- see Behavior of String::num causes parse error for large float fields in Godot inspector godot#93768.

Also: While I don't think my current implementation would be of any use for this proposal as it's bundled with some other changes, I would be willing to implement whatever consensus is reached, if any.

@Calinou
Copy link
Member

Calinou commented Jul 1, 2024

Another option is to limit precision to 6 decimal places regardless of how precise the float actually is (simple but kind of against the point of this whole proposal).

I'd say this is a good enough solution as a first step (7 decimals should work fine, even).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Ready for Implementation
Development

No branches or pull requests

9 participants