BepInEx / BepInEx.ConfigurationManager

Plugin configuration manager for BepInEx
https://www.patreon.com/ManlyMarco
GNU Lesser General Public License v3.0
234 stars 53 forks source link

Text boxes don't scroll horizontally in Valheim #21

Open billw2012 opened 3 years ago

billw2012 commented 3 years ago

Instead the cursor just goes out of view. This is a problem for me as my users paste file paths in there and often these can't be verified as correct because only the first part of the path can be viewed, e.g.: image

ManlyMarco commented 3 years ago

What unity version? The text scrolls fine with the cursor for me.

billw2012 commented 3 years ago

Its 19.4.8f I believe, in Valheim. However I will using the info I found in my other issue https://github.com/BepInEx/BepInEx.ConfigurationManager#overriding-default-configuration-manager-behavior and perhaps replace these with file selection dialog if I am able to.

billw2012 commented 3 years ago

Example: https://i.imgur.com/n2Bsq4S.gif

ManlyMarco commented 3 years ago

This might be because of something in the game's default GUI skin, try changing the GUI.skin.textfield properties and see what happens. I don't have any game where this happens at the moment.

mikeloeven commented 2 years ago

Either way depending on the mod you are configuring this is a pretty major showstopper for anything with long item list strings

AzumattDev commented 2 years ago

Just going to add to this, it happens in Valheim.

jshepler commented 9 months ago

@ManlyMarco

I know this is old, sorry to necro. I'm curious if this lack of horizontal scrolling is something inherent in older versions of unity or if there is some option/style/skin/whatever that can allow it to scroll properly.

This happens with the config manager in the game NGU Idle (unity 2019.4.22) and with my own GUILayout.TextField controls in the game Card Survival - Tropical Island (unity 2019.4.38).

With my own text fields, I tried a number of variations of options, styles, skin settings, and just couldn't get it to work right. Have you done any research/experiments that revealed anything?

If it's just how it works in older versions of unity, and since we can't change that version when modding existing games, is there anything we can do? Maybe something with text align? If aligned right, it obviously scrolls as expected, but starting out right-aligned looks funky. If could somehow know when to swap alignments, maybe we could do that, but I haven't been able to figure out how to tell when the text box is "full" or not. Knowing the length of the string isn't enough as it's not monospaced font and may not know the current width of the box at the time length is being checked.

Anyway, I had given up on it, but thought maybe you had some thoughts.

ManlyMarco commented 9 months ago

@jshepler It seems to be game-specific, with most games not having this issue even when running 2019 unity builds. Still, it appears to be mostly happening on 2019 builds, and I didn't see any 5.x games with this issue.

I tried to fix this briefly in the past and came up empty handed. It might be possible to fix by patching the imgui assembly.

At this point I'm considering trying out different UI frameworks that can also work on IL2CPP like dear-imgui (since imgui is very badly maimed in IL2CPP).

jshepler commented 9 months ago

@ManlyMarco

It might be possible to fix by patching the imgui assembly.

Good call, I traced it down to UnityEngine.TextEditor.UpdateScrollOffset(), at the end it sets m_RevealCursor to false for no reason I could see. So I removed it and now the text scrolls when typing past the end of the box just fine.

ManlyMarco commented 9 months ago

It's a partial workaround, the cursor gets stuck at the end of the box and selecting with mouse gets wonky. It looks like the underlying issue is not inside of UpdateScrollOffset since it's mostly the same as in 5.x where everything worked fine (I tried replacing the method with the old version and it acted exactly the same).

jshepler commented 9 months ago

Looking at the code, it only adjusts the offset when mRevealCursor is true, which makes sense. I don't know why it gets set to false at the end - doing so means next frame won't adjust the offset. Taking those 3 IL instructions out made it work for me. I don't know what might be outside the method that would make it work - maybe if something is constantly sets that field to true every frame? Need to dig more I guess.

The cursor isn't really getting "stuck" at the end - that's just what the offset logic is doing. If you keep pressing left arrow, when the start of the string scrolls into the box, then the text stops scrolling and the cursor goes to the left as you'd expect. Though I do agree doing mouse selection when text is scrolled off to the left is a little wonky, though easy to understand given how the offset gets calculated.

I might play around with a different way to set offset that is smarter about where the cursor is relative to current offset such that the cursor can be moved to the left from the end of the box and the text won't start scrolling to the right until cursor hits the left side of the box - like how we'd expect normal text boxes to work.

But, don't know how that would help you. I looked at 2017.1 and 2023.3 and the code is different for that logic. And you say 5.x is different. So trying to come up with something for the text fields in config manager to work right in any version of unity - ugh.

And you say it depends on the game? Wonder what some games are doing that this doesn't happen. Confusing.

ManlyMarco commented 9 months ago

In the game I tested the cursor is glued to the right edge of the textbox if you do this workaround. Unity 2019.4.9, so it's most likely not the cause, especially since m_RevealCursor is set to false in 5.x in the same way and as far as I can see it's also assigned true in the same places.

jshepler commented 9 months ago

Found something else. In the setter for the position property, it resets scrollOffset to zero to "force its recomputation", but the logic in UpdateScrollOffset depends on the current scrollOffset to know whether to scroll the text left or right - it's already coded to allow the cursor to move freely within the box instead of keeping it at the end, but since scrollOffset is getting reset to zero, it will always be put at the end (until start of the text is inside the left side).

So I added a transpiler patch to remove the line in the position setter that resets scrollOffset to zero. I removed the transpiler patch that removed the line in UpdateScrollOffset that set m_RevealCursor to false. Text still scrolls to the left appropriately and the cursor isn't stuck to the end of the box.

The game I'm modding is NGU Idle, which is a free-to-play game on Steam, if you want to test against Unity 2019.4.22.

What game are you using that has Unity 2019.4.9 and the 5.x one that's already working?

ManlyMarco commented 9 months ago

Koikatu for 5.x and Koikatsu Sunshine for 2019.4.9, but from what I've seen all 5.x games work fine. You could probably decompile assemblies from both versions and compare them to see what changed to find the bug.

jshepler commented 9 months ago

Thought you were trolling me with those games, until I found you made some mods for them.

Can't find where to get it, but steam has the "party" version for $60 that's supposed to be the same game. I don't know if it's using the same version of Unity. Regardless, I'm not going to pay $60 just to dig into the Unity code.

My new fix works fine for me and doesn't stick the cursor to the end of the box.

Good luck.

ManlyMarco commented 9 months ago

You can just download unity editor 5.6 and compile a basic project with only an imgui textbox in it to test it. Or grab reference assemblies for that unity version if you don't need to see it running.

jshepler commented 9 months ago

The reference assemblies only go back to 2017.1, https://github.com/Unity-Technologies/UnityCsReference/blob/2017.1/Runtime/IMGUI/Managed/TextEditor.cs

And they don't have the ... sub-build versions? (not sure what they're called) e.g. there is 2019.4 instead of 2019.4.9 or 2019.4.22 they do, in tags

That's ok, I'm not THAT curious. :)