Indev450 / SRB2Kart-Saturn

GNU General Public License v2.0
24 stars 9 forks source link

Lua HUD interpolation #130

Closed GenericHeroGuy closed 4 months ago

GenericHeroGuy commented 4 months ago

To commemorate one month since My Lie...

This PR adds interpolation to Lua HUD hooks, with two new functions: v.interpolate and v.interpString.

The interpolation works by assigning an unique ID to every call to a HUD drawing function, and using it to track changes in the drawn HUD item's coordinates.

v.interpolate(tag): Enables interpolation (true), or disables it (false). Alternatively, accepts a tag ranging from 0-255. The tag is used to differentiate HUD items drawn by the same function, which is necessary in for loops if some HUD items appear/disappear.

v.interpString(enabled): Enables string mode, which is ~a crutch~ used to overcome some limitations with the interpolation, such as artifacting in custom string drawers. When enabled, the next HUD item drawn will have its interpolation offsets saved and reused for all following draw calls, until string mode is toggled again.

As for how exactly the ID works, it's composed of three parts:

  1. The tag
  2. A counter that is incremented per HUD hook, to separate all of them
  3. The Lua interpreter's program counter (yes, this is absolutely nuts, but HUD hooks have zero frickin' state and I can't wait all day for Lua to dump debug info :rage1:)

Some other changes:

Why did I choose interpolation over uncapping? Mainly because uncapping is a pain to deal with for the Lua scripter, since it requires lots of changes and refactoring to handle properly. Especially since you still have to maintain compatibility with vanilla clients! In most cases, interpolation is a simple drop-in addition. However, it can get hairy in more complex cases, like when dealing with loops, or calling custom drawers... Overall, both methods have their strengths and weaknesses, but in the end I decided on the one that required the least effort on the Lua side. Usually.

Wish I could've made some improvements to the code (the olditem search "algorithm" in particular 😅), but I've slept on this PR for months now, so it's about time I got this out.

And the obligatory test script, which should hopefully give some insight on how this all works: interp_test.txt

GenericHeroGuy commented 4 months ago

Alug and I have been busy interpolating a bunch of Lua scripts, here's some notes:

All in all, plenty of scripts needed interpString hacks to work. Perhaps interpString should be renamed to interpLatch, since that's what it's ultimately used for :stuck_out_tongue:

Now, on uncap vs interp... The biggest problem with interpolation is its inability to snap from point A to B, requiring the interpString hacks I mentioned. Uncapping would've certainly made things like the scoreboard and stage title easier. I'm not sure if converting code to use fixed-point is worse than drawing invisible patches to cope with interp's limitations. The latter is rather unintuitive... (also, uncap can easily support vanilla clients by just... setting the delta to FRACUNIT, duh...)

So what IS interpolation good for then? Well...

So which is better? Or could they co-exist? Who knows.

I'll just rename interpString, and after that... not sure if I have more to add. Well, except making an olditem scanning algorithm that doesn't suck, but I am really struggling for some reason :woozy_face:

GenericHeroGuy commented 4 months ago

I tried improving the olditem search by limiting the search range, but... it didn't make a difference at all? Possibly even made performance worse? Seems like drawlists are just too small for it to make a difference, so I settled for some cleanup.

Indev450 commented 4 months ago

Very nice job, ty for PR c:

alufolie91 commented 4 months ago

1186294931891953768