godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Make floating-point values in the inspector more permissive #10068

Open MrEgggga opened 4 months ago

MrEgggga commented 4 months ago

Describe the project you are working on

A 2D physics-based puzzle platformer

Describe the problem or limitation you are having in your project

I constantly run into issues when changing floating-point values in the inspector:

I mention the actual bugs to point out that these sort of stem from the over-restrictiveness of the Range class and the Godot inspector. However, they should probably be handled separately from this proposal.

Disallowing NaN and Infinity (https://github.com/godotengine/godot/pull/81076) fixed a number of issues where the editor or games crashed when certain fields were set to infinite values, but in my opinion this was a stopgap solution and doesn't really do anything for cases when these fields could be set to NaN via script. In general, I don't see any reason for editing floating points to be this restrictive by default; generally the developer of a game knows what they're trying to do more than the editor does (they might be using NaN in one of their scripts as a special value because Godot currently has no easily-editable way of making optional types in the inspector; they might need a number to be accurate to more than a thousandth; etc.), and making things less restrictive by default in the editor doesn't make things worse for use cases which need the more restrictive behavior; the fields which cause huge problems when set to non-finite values can keep the behavior from https://github.com/godotengine/godot/pull/81076.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Add options in the Range class which can remove some of these restrictions, and enable these by default for exported variables (but not for Range nodes in games).

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

If this enhancement will not be used often, can it be worked around with a few lines of script?

If a specific floating point value is needed that cannot be entered in the inspector (e.g. NaN, 0.12345, pi, 0), it is possible to edit the scene in an external editor and write the exact value in there; however, if the field is touched in the inspector (e.g. by selecting it and pressing Enter) it'll often be rounded again. Exact values can also be set in scripts or as the default export value, but these are kind of inflexible and cumbersome.

Is there a reason why this should be core and not an add-on in the asset library?

This is about changing some core behavior in the editor and is less of a "new feature" than a "fix."

Calinou commented 4 months ago
  • everything entered into a floating point field in the inspector is rounded to the nearest thousandth -- I have had cases where I need more precision and had to either set the value via a script or edit the scene with a text editor

There's already a proposal tracking this: https://github.com/godotengine/godot-proposals/issues/3524

Mickeon commented 4 months ago
  • Add a boolean field allow_infinite with default value false to the Range class that allows for non-finite values.

There's a PR for this but it's not been taken a look at for a bit, maybe by next minor release? https://github.com/godotengine/godot/pull/88354

MrEgggga commented 4 months ago

One thing I'm not sure about for allow_finer: how should unrounded values be shown in the inspector?

If nothing about SpinBox and EditorSpinSlider is changed, the value displayed is rounded, and hovering over the field shows the actual value -- the problem with this is that if you click on the field to edit it, there is no way to get back to the actual value. In my opinion, selecting the text of a field, changing nothing, and pressing Enter to confirm should not change the value of a field.

I can see two ways about this:

For infinite values, I think the solution is much clearer: show their actual values unconditionally rather than showing them as 0 (the current behavior https://github.com/godotengine/godot/issues/88006). I would also say that instead of inf and nan (the behavior if nothing else is changed) they should show as INF and NAN since they must be typed in all caps when editing, but this is less important.


I'm currently working on implementing this proposal for personal use (so far I've implemented the fields described, added hints, and poorly updated SpinBox and EditorSpinSlider according to the second (worse) bullet point above), so if this or one of the many similar issues and proposals linked gets approved I might be able to make a pull request. I could also probably rewrite everything to fit with the pull request https://github.com/godotengine/godot/pull/88354 linked above.

MrEgggga commented 4 months ago

I'm mostly done with the interesting part of implementing this proposal; currently I have the following things left:

I would also have to update the range hint of every single float field in Godot's codebase (around 875 fields) for these features to be of any use. I plan on doing this, but I'm not sure whether it should be in the same pull request or separate.

What I have so far is available at https://github.com/MrEgggga/godot/tree/permissive-range. (So far I've been making most of my commits fairly small, but according to the contributing guidelines in the documentation it seems like it would be best to squish everything into one commit.)


One issue I ran into when implementing this was that fields which are stored as real_t or float rather than double looked terrible when not rounded properly (e.g. if you typed 0.12345 into one of the components of a Vector3 and pressed Enter, it would change to 0.12345000356436). My solution for this (not yet committed as of this post) is a bit hacky:

I'll probably have to rewrite pretty much all of this if I want to account for single-precision float fields as well as real_t fields seeing as real_t isn't necessarily single-precision, and this all just feels kind of ugly in general (although I can't think of any better solution). One thing I'm unsure of is how much of this should be exposed -- right now it's possible to use the real_t hint with export_range in GDScript, but it's not in the autocomplete and there's very little point in it as GDScript floats are always double-precision.


One issue that wasn't a problem before (because it was covered up by a bigger problem) but might come up in the future is that values that are too small (around 5e-15 for double-precision fields and 5e-7 for single-precision) will be rounded to zero (see https://github.com/godotengine/godot/issues/93768). This probably isn't that big a deal (for quite a while it's been impossible to input float values less than 5e-4 and have them stick), but I personally think that the inspector should use scientific notation for large and small values, both for readability and to ensure that information is not lost when EditorSpinSlider converts floats to strings back and forth. However, this probably belongs in a separate proposal.