It has been suggested to merge this page with UI Scale.

UI scaling

From Warcraft Wiki
(Redirected from UIParent)
Jump to navigation Jump to search


Scaling shrinks or expands the user interface. Instead of pixels, lengths measure in scaled units equal to 1/768 of the screen height multiplied by a ratio.

For measuring a point on the screen, this ratio is 1.0. For measuring widgets, this ratio is usually the UI Scale that is user-configurable in the System settings.

Screen units

Functions like GetCursorPosition() measure from the bottom-left corner (0, 0). The maximum visible Y coordinate is always 768, while the maximum visible X coordinate depends on aspect ratio:

Aspect ratio Width Height
4:3 1024 768
5:4 960 768
16:9 1365⅓ 768
16:10 1228.8 768

Values outside these ranges represent an overflow beyond the screen edges.

Region units

Region:SetScale() resizes a Region, and also its children, children's children, and so on. If a child also has scale, the values multiply and the product is an effective scale. Lengths measured about a Region use region units per the following formula:

region:GetEffectiveScale() * screenHeight / 768

Region units apply to the following length measurements:

  • Region:GetLeft() - Distance from the left of the screen to the left of the Region.
  • Region:GetRight() - Distance from the left of the screen to the right of the Region.
  • Region:GetBottom() - Distance from the bottom of the screen to the bottom of the Region.
  • Region:GetTop() - Distance from the bottom of the screen to the top of the Region.
  • Region:GetWidth() - Distance from the left to right of the Region.
  • Region:GetHeight() - Distance from the bottom to top of the Region.
  • Region:GetSize() - Combination of GetWidth() and GetHeight().
  • Region:GetRect() - Combination of GetLeft(), GetBottom(), GetWidth() and GetHeight().

FrameXML has functions to compare regions independent of their effective scale:

UIParent

Most user interface elements are parented by UIParent that covers the whole screen. Addons inserting widgets into the UI should consider making them children of UIParent (or within its heirarchy of children) to inherit a common scale.

The System window, within "Graphics", presents a checkbox and slider corresponding to console variables useUiScale and uiScale. Disabling this option causes UIParent to adopt a default scale per the table below:

Default UIParent scale
Resolution Retail Classic
2560x1440 0.64 0.90
1920x1080 1.00 1.00
1280x1024 0.79 0.90
1024x768 1.00 1.00

Conversely, enabling the option allows the user to set a custom scale. Finer-grained scaling is possible with the /console command to set each console variable.

Pixel perfect UI

Due to rounding and snapping to pixels, visual oddities can appear when a Texture borders or overlaps another. To eliminate these visual glitches, one strategy is to set a custom UIScale ratio so that one unit equals one pixel.

For screens up to a height of 1200px, this is possible by setting CVar uiScale to equal 768/vRes where vRes is the vertical resolution. For example, on a 1920x1080:

/console useUiScale 1
/console uiScale 0.7111

For screens with a vertical resolution beyond 1200px, the formula would result in a uiScale less than 0.64 which the game will ignore. To workaround this, override the scale manually on UIParent after the game loads (or use an addon such as UIScale). For example, on a 2560x1440:

UIParent:SetScale(0.5333)

Examples

Setting a "pixel perfect" UI with a 1920x1080 resolution, using an AddOn:

C_CVar.SetCVar("useUiScale", 1)
C_CVar.SetCVar("uiScale", 768/1080)

Checking if the cursor is over a frame:

function MouseIsOver(frame)
	local x, y = GetCursorPosition();
	local s = frame:GetEffectiveScale();
	x, y = x/s, y/s;
	return ((x >= frame:GetLeft()) and (x <= frame:GetRight())
		and (y >= frame:GetBottom()) and (y <= frame:GetTop()))
end

Checking if two frames overlap:

function FramesOverlap(frameA, frameB)
	local sA, sB = frameA:GetEffectiveScale(), frameB:GetEffectiveScale();
	return ((frameA:GetLeft()*sA) < (frameB:GetRight()*sB))
		and ((frameB:GetLeft()*sB) < (frameA:GetRight()*sA))
		and ((frameA:GetBottom()*sA) < (frameB:GetTop()*sB))
		and ((frameB:GetBottom()*sB) < (frameA:GetTop()*sA))
end

Patch changes

  • Bc icon.gif Patch 2.0.1 (2006-12-05): Return values from functions like Region:GetWidth() now always use scaled Region units, even when the size is implicitly computed from anchors without an explicit call to Region:SetWidth() or similar.