Plexus

Plexus

430k Downloads

[Bug] My frame keeps moving on re-log.

rainx0r opened this issue ยท 10 comments

commented

Describe the bug
What it says on the tin. My raid / party frames keep moving. Through debugging, I found this is always exactly 5 pixels off on each dimension each re-log. Say my frames are on PosX = -93, PosY=76, anchor="BOTTOMRIGHT", next re-log this will be -88, 71.

For whatever reason, this ONLY happens when re-logging, not when reloading.

To Reproduce
I can give you my profile / SavedVariables and other things upon request,

I did manage to do a band-aid fix, but I'd like to use this issue to describe to you my scenario, testing and poking around work, and hopefully since you know your codebase better than me maybe you can derive some better, generally applicable solution!

The scenario

  • Prior: I used to use Grid1, moved over to Plexus around BFA or Shadowlands, don't remember. My original UI was made for 1080p, I'm now on 1440p.
  • The environment: Game running natively at 1440p, UI is at 80% scale (UIParent:GetEffectiveScale() = 0.79999995231628). Note that this is also the value of PlexusLayoutFrame:GetEffectiveScale()

Every time I re-log, the following things happen:

  • PlexusLayout:PostEnable() gets triggered.
  • This calls PlexusLayout:RestorePosition() which reads the PosX, PosY, anchor from the profile, divides them by the scale and rounds up, then sets the position. Up to here, according to my logs, everything seems to work fine. This function reads the correct values, the conversion looks correct, and it restores my UI to the correct position, if I comment out everything that happens after this function.
  • Then PlexusLayout:Scale() gets called which:
    • Calls PlexusLayout:SavePosition(), which is where things seem to go wrong according to my logs. If I check what profile.PosX / profile.PosY is at the beginning of this function, it's the value RestorePosition() set. However, the value that gets saved back to the profile in that last if statement is 5 pixels off. This means the value retrieved from all the calculations in the anchor if chain is actually somehow 5 pixels off.
    • RestorePosition() gets called again, this time placing my frame in the incorrect position of 5 pixels off. This position then gets saved to my SavedVariables when I log out. Since every time a value 5 pixels off gets saved, my frame moves eternally every re-log.

My "band-aid" fix
In PlexusLayout:SavePosition()

    ...
    if x and y and s then
        x, y = floor(x - 5 + 0.5), floor(y + 5 + 0.5)
        self.db.profile.PosX = x
        self.db.profile.PosY = y
        ...
    end

For whatever reason, this fixes the problem on re-log, and the values that get saved agree with the values there before / the ones RestorePosition originally used when loading the frame, and my frame does not move every re-log any more.

But then the problem starts happening on /reload instead. The problem did not happen on /reload before. However, this demonstrates that it's literally just 5 pixels off.

My second fix was this:
PlexusLayout:PostEnable()

    -- position and scale frame
    self:RestorePosition()
    -- self:Scale()
    self.frame:SetScale(self.db.profile.scale)
    self:RestorePosition()

Now the frame works perfectly both on re-log and reload.

Potential clues

  • Maybe this is a quirk of Blizzard's UI code and how they handle different scales / resolutions, especially on re-log. For whatever reason, when you set the position with RestorePosition() but then try to re-infer its coordinates in SavePosition() immediately after (as in the flow introduced by PostEnable()), maybe you get 5 pixel off values for whatever reason.
  • When you really think about it though, there is no reason for this flow, since you just set the frame's position programmatically, so it has no chance of changing position, making the problematic SavePosition() call redundant. As far as I can tell with my fix everything works as expected.

Desktop (please complete the following information):

  • OS: Windows 11
  • Version: 2.4.7 (But Layout.lua, where the bug is, has not changed in 2.4.9)
  • Game Version: 10.0.2
commented

Probably?

    -- position and scale frame
    self:RestorePosition()
    self.frame:SetScale(self.db.profile.scale)

might work too. The frame is already created, just RestorePosition() calculates its coordinates given the coords and scale saved in the profile, and SetScale() just applies said saved scale to the frame, which can happen before or after it's positioned and it shouldn't matter. But you're right since none of the "dependent" variables of RestorePositon() change between these two calls, the duplicate call is probably not needed.

commented

Honestly, I can only assume it is a bug on Blizzard's end, or it only happens under certain circumstances. For clarity, my fix is only the second code block I posted, the first code block should not be used, just it was the first thing I tried.

commented

I have had a few people say this happened to them in the past however, I myself have gone from 1080p to 4k and never noticed this bug so I was never really able to reproduce. Since you seem to have a fix that works for you I will try and see if it breaks anything in my setup where I have not seen this bug and if it works maybe I can just merge it, thank you for your thorough research into this.

I was never able to find out exactly what was happening because I could never get it to happen for me.

commented

@evangelos-ch yes, I beleieve I follow what you said, I tested just loading in the game and loggging in/out a few times and /reload a few times and it seems to be fine, I just want to look into it a bit more before making it a release but if it works for you and me without issue then maybe I will push it out, let me know if it continues to work for you.

commented

I was just looking and trying to track the code flow to see what is called when and by what, I was just thinking do we need double self:RestorePosition()?
Or can

    -- position and scale frame
    self:RestorePosition()
    self.frame:SetScale(self.db.profile.scale)
    self:RestorePosition()

become

    -- position and scale frame
    self.frame:SetScale(self.db.profile.scale)
    self:RestorePosition()

I think the second still works no?

commented

Just wanted to let you know that this fix has been working fine for me for over a month now, so I'd definitely recommend incorporating it into one of your new releases (would really save me the trouble of doing it manually when I update the addon from curseforge)

commented

@evangelos-ch to be clear before I push this out

`
-- position and scale frame

self.frame:SetScale(self.db.profile.scale)

self:RestorePosition()

`

or

`
-- position and scale frame

self:RestorePosition()

self.frame:SetScale(self.db.profile.scale)

`

commented

I was playing with the code change for a while and didn't notice any difference but almost forgot about the change with the other addon work i've been doing.

commented

Fixed: 0264476

commented

reverted because others started saying this fix broke it for them, neither had any effect for me so idk.