Thread Tools Display Modes
12-14-18, 11:47 PM   #1
Lyak
A Cyclonian
Join Date: Jul 2018
Posts: 46
Achieving pixel perfection

Hi all,

I wasn't really worried about the pixel perfection, but my frames started to cause an issue with the placement and sizing.

Where should I start? If possible, I would like to get some explanation on how and why(?) it works rather than just using an already existing solution.

Could anyone please help me out regarding this?

Thank you!
  Reply With Quote
12-15-18, 02:51 AM   #2
d87
A Chromatic Dragonspawn
 
d87's Avatar
AddOn Author - Click to view addons
Join Date: Jan 2006
Posts: 163
WoW screen is using these sort of floating point virtual pixels, they go up to 768 in height and proportionally for aspect ratio in width, and they map onto your real resolution. And then there's possibly global UI scale in the mix. In the end the line that you wanted to be 2 virtual pixels wide ends up snapping to either 2 or 3 real pixels depending on where it is
So you need to reverse this process and find out what amount of virtual pixels is corresponding to real pixels

Here's what i use to find it:
Code:
local res = GetCVar("gxWindowedResolution")
if res then
    local w,h = string.match(res, "(%d+)x(%d+)")
    pmult = (768/h) / UIParent:GetScale()
end
Not sure if consistently using whole number of real pixels guarantees perfection, but in my experience it makes it better at least. Also ideally you don't want to use UI scale
  Reply With Quote
12-15-18, 03:39 AM   #3
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,240
If your display, or if writing a public addon, the user's display, is greater than 1920x1080, you need to do two things:
  1. Set the CVar scale to 768/height
  2. Set UIParent's scale to 768/height
This is because WoW won't let you set a CVar scale lower than 0.64 which won't look correct on monitors with a resolution greater than 1080p.

If the height is equal to or less than 1920, only do the first thing. Now here are the hard parts:
  1. Scale your frame initially by the above scale, in which it will look tiny with unreadable text.
  2. Increase the height and/or width of the frame until it looks good, but leave the scale alone.
  3. As mentioned, you need to place your newly scaled frame on an even pixel, unless that isn't centered. You'll have to figure that out frame by frame.
  4. Assuming you let the user set a scale, which is a bad idea at this point, wrap your "user scale" instead in height or width adjustments providing the illusion of scaling up or down. A better idea is to not provide a scaling option and go straight for height or width.
  5. Place the adjusted frame again so it sits evenly.
  Reply With Quote
12-15-18, 08:40 PM   #4
Lyak
A Cyclonian
Join Date: Jul 2018
Posts: 46
Originally Posted by d87 View Post
WoW screen is using these sort of floating point virtual pixels, they go up to 768 in height and proportionally for aspect ratio in width, and they map onto your real resolution. And then there's possibly global UI scale in the mix. In the end the line that you wanted to be 2 virtual pixels wide ends up snapping to either 2 or 3 real pixels depending on where it is
So you need to reverse this process and find out what amount of virtual pixels is corresponding to real pixels

Here's what i use to find it:
Code:
local res = GetCVar("gxWindowedResolution")
if res then
    local w,h = string.match(res, "(%d+)x(%d+)")
    pmult = (768/h) / UIParent:GetScale()
end
Not sure if consistently using whole number of real pixels guarantees perfection, but in my experience it makes it better at least. Also ideally you don't want to use UI scale
So, basically what wow does is it take the real value, goes through some calculation then converts the real value to wow sepcific virtual value. Am I getting it right?

And after all what I'll have to do is multiply pmult whenever I'm setting the position or the size?

Like:
Lua Code:
  1. frame:SetSize(width * pmult, height * pmult);
  2. frame:SetPoint("CENTER", UIParent, "CENTER", oX * pmult, oY * pmult);

Originally Posted by myrroddin View Post
If your display, or if writing a public addon, the user's display, is greater than 1920x1080, you need to do two things:
  1. Set the CVar scale to 768/height
  2. Set UIParent's scale to 768/height
This is because WoW won't let you set a CVar scale lower than 0.64 which won't look correct on monitors with a resolution greater than 1080p.

If the height is equal to or less than 1920, only do the first thing. Now here are the hard parts:
  1. Scale your frame initially by the above scale, in which it will look tiny with unreadable text.
  2. Increase the height and/or width of the frame until it looks good, but leave the scale alone.
  3. As mentioned, you need to place your newly scaled frame on an even pixel, unless that isn't centered. You'll have to figure that out frame by frame.
  4. Assuming you let the user set a scale, which is a bad idea at this point, wrap your "user scale" instead in height or width adjustments providing the illusion of scaling up or down. A better idea is to not provide a scaling option and go straight for height or width.
  5. Place the adjusted frame again so it sits evenly.
Let me get things one by one.

If the screen size is greater than 1920x1080, I'll have to set both UIScale CVar and UIParent's scale to 768/height as you have advised. However, if I switch UIParent's scale to such, wouldn't that affect all other frames having UIParent as a parent frame? If the answer is yes, would it be okay to use my own UIParent like the following to avoid such issues?

Lua Code:
  1. local uiParent = CreateFrame("Frame", nil, UIParent);
  2. uiParent:SetAllPoints(true);
  3. uiParent:SetScale(xxxx);
  4.  
  5. addon.UIParent = uiParent;
  6.  
  7. local frame = CreateFrame("Frame", nil, addon.UIParent);
  8. -- Continue positioning, sizing and etc.

Last edited by Lyak : 12-15-18 at 08:43 PM.
  Reply With Quote
12-16-18, 06:14 AM   #5
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,240
About UIParent, yes, that would be true, which is why, among other pixel perfect enabled addons, ElvUI creates their own "ElvUIParent". I'm not 100% sure of what name they chose, but it doesn't matter, as that is just a variable.

When doing pixel perfection, ElvUI doesn't scale UIParent, instead scaling their own version then SetAllPoints so it fits on UIParent.

This has the added benefit of not messing with other addons that depend on UIParent's scale.
  Reply With Quote
12-16-18, 06:33 AM   #6
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,240
While I have never tested it, I'm going to assume that your pmult example will be not what you want if you multiply height and width.

Height and width are integers representing pixels. If pmult is not an integer (it will always be a real or whole number, never an integer) then there is no possible way for either height or width to sit on a pixel. Instead, height and width will sit in between pixels, and look wrong.

That's why I suggested to never apply pmult to height or width. Scale on the other hand is a whole or real number, which means it includes integers, albeit as 1.0, 2.0, 3.0 rather than 1, 2, 3.

Should you be hellbent on allowing pmult on height or width, then you need to round up or down to the nearest integer after you multiply by pmult. It's a couple of extra steps.

When rounding, I further suggest a couple of sanity checks:
  • Use advanced rounding. If < 0.5 then round down, if >= 0.5 round up.
  • Use SetClampedToScreen(true). It becomes your friend.
  • Check that your rounded value is >=1 and <= (width - frameSize). You are trying to get the frame to fit on UIParent.
  • Double check height and width are modulo 2 == 0 (% 2 == 0). Should the result <= 1 and you are trying to center the frame, use math.ceil. That's the best you can do.

Last edited by myrroddin : 12-16-18 at 06:35 AM. Reason: typo
  Reply With Quote
12-17-18, 02:40 PM   #7
Lyak
A Cyclonian
Join Date: Jul 2018
Posts: 46
Originally Posted by myrroddin View Post
That's why I suggested to never apply pmult to height or width. Scale on the other hand is a whole or real number, which means it includes integers, albeit as 1.0, 2.0, 3.0 rather than 1, 2, 3.
So, your original solution would not cause such issues, right?

Hm... if that's the case I should stick to your way.

Let me test them first and I'll come back for further advice.

Thank you!
  Reply With Quote
01-14-19, 05:48 PM   #8
Leaker
A Murloc Raider
Join Date: Jan 2019
Posts: 6
Originally Posted by myrroddin View Post
If your display, or if writing a public addon, the user's display, is greater than 1920x1080, you need to do two things:
  1. Set the CVar scale to 768/height
  2. Set UIParent's scale to 768/height
This is because WoW won't let you set a CVar scale lower than 0.64 which won't look correct on monitors with a resolution greater than 1080p.

If the height is equal to or less than 1920, only do the first thing. Now here are the hard parts:
  1. Scale your frame initially by the above scale, in which it will look tiny with unreadable text.
  2. Increase the height and/or width of the frame until it looks good, but leave the scale alone.
  3. As mentioned, you need to place your newly scaled frame on an even pixel, unless that isn't centered. You'll have to figure that out frame by frame.
  4. Assuming you let the user set a scale, which is a bad idea at this point, wrap your "user scale" instead in height or width adjustments providing the illusion of scaling up or down. A better idea is to not provide a scaling option and go straight for height or width.
  5. Place the adjusted frame again so it sits evenly.
I am also interested in creating a pixel perfection, but having difficulties with fully understanding your method as a newb developer

If you don't mind, could you please provide me some working example?

My current screen resolution is 1920x1080, but am not willing to limit this to such.

Many thanks!
  Reply With Quote
01-15-19, 06:49 PM   #9
myrroddin
A Pyroguard Emberseer
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 1,240
https://wow.gamepedia.com/UI_Scale
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Achieving pixel perfection

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off