WoW:UI coordinates
The WoW User Interface engine is designed to provide a consistent UI look regardless of screen shape or resolution, and thus scaling is a pervasive part of the WoW User Interface. While this is generally transparent to users of the game, it can cause some confusion for developers, since different sets of functions operate with different scaled coordinate systems. This document tries to provide consistent naming and a description of each one.
Origin and Axes
The origin is generally the BOTTOM LEFT corner of the screen. X coordinates always increase to the RIGHT (and decrease LEFT), and Y coordinates always increase UP (and decrease DOWN).
Coordinate Systems
Real Screen Coordinates
The actual SIZE of the user's screen isn't readily available from the game, though you can query the current video settings for users that are not playing in windowed mode, to find out. Windowed mode presents somewhat of a challenge, because there the video settings determine the shape of the window, but the user can resize it on screen to whatever height or width they wish. It's best to just forget all about the real screen size anyway, and concentrate instead on the UI Root Coordinates:
UI Root Coordinates
WoW normalizes all screen resolutions to be 768 pixels high, and then an aspect-appropriate width. Thus any 4:3 screen resolution appears as 1024x768, any 5:4 as 960x768, and 16:10 as 1228.8x768. The virtual "root" frame, which all non-parented frames are children of, then has this normalized size.
The x,y = GetCursorPosition() function returns the x,y location in UI Root Coordinates, with the origin in its standard BOTTOM LEFT screen corner location.
(Prior to WoW 2.0, for frames with anchor-defined sizes (not forced sizes), w = layoutFrame:GetWidth() and h = layoutFrame:GetHeight() return values in the UI Root Coordinate system.)
Frame Scaled Coordinates
Most frame-specific coordinate functions operate in a coordinate system that is adjusted by the Frame's effective scale (As returned by effScale = frame:GetEffectiveScale(). Each unit in the frame scaled coordinate system corresponds to effScale units in the UI Root coordinate system. The origin, however, is still the BOTTOM LEFT corner of the screen.
The main methods which return values in Frame Scaled Coordinates are x = frame:GetLeft(), x = frame:GetRight(), y = frame:GetBottom(), y = frame:GetTop(), x,y = frame:GetCenter(), and l,b,w,h = frame:GetRect()
In addition, anchor offsets, as controlled by layoutFrame:SetPoint("POINT","RelativeFrame","RELPOINT",x,y) and the anchoring XML elements, are also specified in the Frame Scaled coordinate system of the point that is being anchored, but are relative to the attachment point on the relative frame. This can sometimes have surprising results if the layoutFrame and RelativeFrame have different effective scales.
w = layoutFrame:GetWidth() and h = layoutFrame:GetHeight() return values in the Frame Scaled coordinate system, and the corresponding set functions layoutFrame:SetWidth(w), and layoutFrame:SetHeight(h) take values in the Frame Scaled coordinate system.
Useful Code Snippets
Cursor Over 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
Frame 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