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:
The tag
A counter that is incremented per HUD hook, to separate all of them
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:
The game drawlist has been separated into one per splitscreen player, to avoid artifacting
The drawitem struct has been shrunk significantly to compensate for the double-buffering of drawlists
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
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:
* The `game` drawlist has been separated into one per splitscreen player, to avoid artifacting
* The drawitem struct has been shrunk significantly to compensate for the double-buffering of drawlists
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](https://github.com/Indev450/SRB2Kart-Saturn/files/15420678/interp_test.txt)
Alug and I have been busy interpolating a bunch of Lua scripts, here's some notes:
Driftgauge, nametags and Mini Rankings Plus were all one-liners
Fancy roulette suffers from the item being off-center with no easy fix, but is otherwise fine (just one interpString hack)
Dino Stage Title went well minus the interpString hacks (drawing an invisible patch moving at the scroll speed, and applying the interpolation offsets to other patches)
Neo Scoreboard needed some wacky interpString abuse to deal with the multi-directional scrolling; 32P vertical scrolling, plus the horizontal name scrolling I added a while ago. Name scrolling looks pretty janky because it scrolls too slowly for the interp to work properly.
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 😛
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...
It allows screencoords scripts like driftgauge and nametags to be smoothed. Doing the same with uncap would require exposing mobj and camera interpolation.
It allows for subpixel drawString movement, which would otherwise require either V_NOSCALESTART, the fixed font, or a custom drawer.
I have no numbers to back it up, but interpolation ought to be lighter on the CPU than uncapping, since the latter requires running Lua code every frame, instead of every tic.
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 🥴
Alug and I have been busy interpolating a bunch of Lua scripts, here's some notes:
* Driftgauge, nametags and Mini Rankings Plus were all one-liners
* Fancy roulette suffers from the item being off-center with no easy fix, but is otherwise fine (just one interpString hack)
* Dino Stage Title went well minus the interpString hacks (drawing an invisible patch moving at the scroll speed, and applying the interpolation offsets to other patches)
* Neo Scoreboard needed some wacky interpString abuse to deal with the multi-directional scrolling; 32P vertical scrolling, plus the horizontal name scrolling I added a while ago. Name scrolling looks pretty janky because it scrolls too slowly for the interp to work properly.
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...
* It allows screencoords scripts like driftgauge and nametags to be smoothed. Doing the same with uncap would require exposing mobj and camera interpolation.
* It allows for subpixel drawString movement, which would otherwise require either V_NOSCALESTART, the `fixed` font, or a custom drawer.
* I have no numbers to back it up, but interpolation *ought* to be lighter on the CPU than uncapping, since the latter requires running Lua code every frame, instead of every tic.
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:
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.
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.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
To commemorate one month since My Lie...
This PR adds interpolation to Lua HUD hooks, with two new functions:
v.interpolateandv.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 inforloops if some HUD items appear/disappear.v.interpString(enabled): Enables string mode, which isa crutchused 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:
Some other changes:
gamedrawlist has been separated into one per splitscreen player, to avoid artifactingWhy 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
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 😛
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...
fixedfont, or a custom drawer.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 🥴
Looks good
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.
Very nice job, ty for PR c: