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

Animation Player FPS shows rounded integer but still internally stores float converted from Seconds #97548

Closed
hsandt opened this issue Sep 27, 2024 · 5 comments · Fixed by #97569

Comments

@hsandt
Copy link
Contributor

hsandt commented Sep 27, 2024

Tested versions

  • Reproducible in: v4.3.stable.official [77dcf97]
  • Not reproducible in: v4.2.1.stable.official [b09f793]

System information

Godot v4.3.stable - Ubuntu 22.04.4 LTS 22.04 - X11 - GLES3 (Compatibility) - NVIDIA GeForce GTX 860M (nvidia; 535.183.01) - Intel(R) Core(TM) i7-4710HQ CPU @ 2.50GHz (8 Threads)

Issue description

Context

I am working with fractional FPS for animations, since I set frame time in ms (in Aseprite) then calculate the corresponding FPS for an Animated Sprite (1000/frame duration in ms), then use a converter (Animated Sprite to Animation Player Convertor for Godot 4.0) from Animated Sprite to Animation Player animation. This leads to FPS such as 12.5 FPS for 80ms frames.

So far in Godot v4.2.1 I could enter either 12.5 FPS or 80ms at the bottom of the Animation Player to get the snapping I wanted:

image

Issue

Since Godot 4.3, the FPS field only allows entering an integer. Entering a float will round it and display the rounded integer. This leads to imperfect FPS such as 13 instead of 12.5, leading to snapping between frames (observe the vertical blue bar not being snapped to the start of a sprite square preview):

image

image

I need to switch back to Seconds, then enter 0.08 and then switch back to FPS to get 12.5 FPS internally:

image

image

However, note that the rounded value 13 FPS is still displayed:

image

although snapping shows we are really still at 12.5 FPS / 80ms:

image

This is confusing, and furthermore, trying to re-enter 13 FPS manually will not change the value to 13. However, entering a different value like 14, then the old value 13 again will force refresh to 13 instead of 12.5.

Fix suggestion

Revert to showing fractional FPS as before, since they are still stored internally as such as indirectly accessibly via setting Seconds, but this requires an extra step for the user.

Currently there is not even an up/down arrow widget to increase/decrease FPS by 1, so there is no big advantage in showing integers anyway (and we could still add an up/down arrow for people who really want to use integers if we want to).

Steps to reproduce

  • Create an Animation Player node with a dummy animation track (the easiest to test timeline snapping is to manually increase the animation duration near the clock icon at the top-right)
  • In the Animation Player panel, try to change FPS to a fractional value like 12.5 => rounded to 13
  • Move the timeline vertical bar around to test snapping. Add some keyframes there to remember the positions.
  • Switch to Seconds, enter 0.08, switch back to FPS => see 13 but internally it's 12.5
  • Move the timeline vertical bar around to test snapping. See how it ends at different positions that the previous keyframes.
  • Enter 14 FPS, confirm, then 13 again, confirm (to force value refresh).
  • Move the timeline vertical bar around to test snapping. See how it's now snapping to the previous keyframes.

Minimal reproduction project (MRP)

N/A

@AtlaStar
Copy link
Contributor

Looks possibly related to #92670
image

Gonna perform a bisect to be certain, but it also appears that it is intentional. It also seems likely this was the PR that produced the issue given this function given that swapping from seconds to FPS just uses the 1.0/step->get_value() to determine the new snapping value rather than ensuring that the FPS value is an integer value first, while it does appear to round when swapping from FPS to seconds.

image

@AtlaStar
Copy link
Contributor

confirmed that commit b83dc9b from PR #92670 is what introduced this bug.

Also noting that it exists on Windows 10, along with every other platform afaict.

@AtlaStar
Copy link
Contributor

I am wondering if a solution would be to allow fractional values, but have the result round to the nearest eighth, or sixteenth when read from the TSCN. This would implicitly fix the issue with loading 60 fps as 59.9999 FPS as it would round up to 60 FPS and negate the precision errors that would arise, and shouldn't be so precise as to allow issues to arise.

AtlaStar added a commit to AtlaStar/godot that referenced this issue Sep 28, 2024
Closes godotengine#97548. Care also taken to not reopen issue godotengine#92273 by ensuring that the value rounds to the nearest sixteenth. Optionally any factor of 2 should work while ensuring that there isn't error accumulation.

Further testing to ensure issue godotengine#91729 isn't reopened, but initial testing suggests that the issue will not reopen with this PR.
@TokageItLab
Copy link
Member

TokageItLab commented Sep 28, 2024

As I said there, only integers are allowed in the FPS is intended, not a bug. Also, it is not a regression, since there was a problem with #92273 before and the float FPS was not handled correctly Unless the result of 1/FPS is rational and few decimals. If #97569 does not cause error problems after serialization, then it is fine and this issue can be fixed, but if not, then it needs some other approach, like serializing the FPS directly, not convert to second.

I am wondering if a solution would be to allow fractional values, but have the result round to the nearest eighth, or sixteenth when read from the TSCN

Wouldn't this result in a different FPS value being serialized than the last set and the snap being shifted the next time the editor is opened? If rounding is performed when loading tscn, the same rounding must be performed when setting the fractional FPS in the editor. In other words, we cannot allow high precision float FPS anywhere on the editor if rounding is performed when loading tscn.

The bug here is that (if I am correct in my understanding of description), after switching from Second to FPS, the FPS is internally set to a fractional FPS, so snapping at the time of switching would be the correct fixing way. Currently, the value that should be snapped is 1.0, and float FPS should not be allowed.

Given the precision issues in the time <-> FPS conversion, a snapping value of about 0.1 or 0.01 might be allowed theoretically. However, float FPS is not allowed in other places such as the Project settings. I understand that the editor can be manipulated independently of the drawing, but I doubt that float FPS snapping is really needed there.

@TokageItLab TokageItLab added this to the 4.x milestone Sep 28, 2024
@TokageItLab TokageItLab changed the title (Regression in v4.3) Animation Player FPS shows rounded integer but still internally stores float converted from Seconds Animation Player FPS shows rounded integer but still internally stores float converted from Seconds Sep 28, 2024
@AtlaStar
Copy link
Contributor

To clarify the train of thought here; instead of allowing any and all fractional values for the FPS, instead you clamp the entered value to a value rounded to the nearest 16th. So typing in 15.0541 would clamp it to 15.0625 which is 15 and 1/16. Typing in 12.46 would round to 12.4375 or 12 and 7/16. These values would then be used to save to the tscn.

As to what I believe this report was reporting; it seems to be reporting 2 different "bugs"; the first being the change in behavior which your PR closed as noted above which isn't a bug but a change in intended behavior. The second half and actual bug is that changing between FPS and Seconds doesn't actually change the FPS value, just how it is displayed, as you mentioned.

AtlaStar added a commit to AtlaStar/godot that referenced this issue Sep 29, 2024
Closes godotengine#97548. Care also taken to not reopen issue godotengine#92273 by ensuring that the value rounds to the nearest sixteenth. Optionally any factor of 2 should work while ensuring that there isn't error accumulation.

Further testing to ensure issue godotengine#91729 isn't reopened, but initial testing suggests that the issue will not reopen with this PR.
@TokageItLab TokageItLab modified the milestones: 4.x, 4.4 Sep 29, 2024
AtlaStar added a commit to AtlaStar/godot that referenced this issue Oct 2, 2024
Closes godotengine#97548. Care also taken to not reopen issue godotengine#92273 by ensuring that the value rounds to the nearest sixteenth. Optionally any factor of 2 should work while ensuring that there isn't error accumulation.

Further testing to ensure issue godotengine#91729 isn't reopened, but initial testing suggests that the issue will not reopen with this PR.
laurentmackay pushed a commit to metapfhor/godot that referenced this issue Oct 30, 2024
Closes godotengine#97548. Care also taken to not reopen issue godotengine#92273 by ensuring that the value rounds to the nearest sixteenth. Optionally any factor of 2 should work while ensuring that there isn't error accumulation.

Further testing to ensure issue godotengine#91729 isn't reopened, but initial testing suggests that the issue will not reopen with this PR.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants