|
|
|
|
--------------------------------------------
|
|
|
|
|
-- http://wow.gamepedia.com/UI_Scale
|
|
|
|
|
-- http://www.wowinterface.com/forums/showthread.php?t=31813
|
|
|
|
|
--------------------------------------------
|
|
|
|
|
local addonName, addon = ...
|
|
|
|
|
addon.pixelPerfectFuncs = {}
|
|
|
|
|
local P = addon.pixelPerfectFuncs
|
|
|
|
|
|
|
|
|
|
function P:GetResolution()
|
|
|
|
|
-- return string.match(({GetScreenResolutions()})[GetCurrentResolution()], "(%d+)x(%d+)")
|
|
|
|
|
return GetPhysicalScreenSize()
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- The UI P:Scale goes from 1 to 0.64.
|
|
|
|
|
-- At 768y we see pixel-per-pixel accurate representation of our texture,
|
|
|
|
|
-- and again at 1200y if at 0.64 scale.
|
|
|
|
|
function P:GetPixelPerfectScale()
|
|
|
|
|
local hRes, vRes = P:GetResolution()
|
|
|
|
|
if vRes then
|
|
|
|
|
return 768 / vRes
|
|
|
|
|
else -- windowed mode before 8.0, or maybe something goes wrong?
|
|
|
|
|
return 1
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- scale perfect!
|
|
|
|
|
function P:PixelPerfectScale(frame)
|
|
|
|
|
frame:SetScale(P:GetPixelPerfectScale())
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- position perfect!
|
|
|
|
|
function P:PixelPerfectPoint(frame)
|
|
|
|
|
local left = frame:GetLeft()
|
|
|
|
|
local top = frame:GetTop()
|
|
|
|
|
|
|
|
|
|
frame:ClearAllPoints()
|
|
|
|
|
frame:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", math.floor(left + 0.5), math.floor(top + 0.5))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--------------------------------------------
|
|
|
|
|
-- PixelUtil
|
|
|
|
|
--------------------------------------------
|
|
|
|
|
-- local effectiveScale = 1
|
|
|
|
|
-- function P:SetRelativeScale(scale)
|
|
|
|
|
-- effectiveScale = scale
|
|
|
|
|
-- end
|
|
|
|
|
|
|
|
|
|
-- function P:GetEffectiveScale()
|
|
|
|
|
-- return effectiveScale
|
|
|
|
|
-- end
|
|
|
|
|
|
|
|
|
|
-- function P:SetEffectiveScale(frame)
|
|
|
|
|
-- frame:SetScale(effectiveScale)
|
|
|
|
|
-- end
|
|
|
|
|
|
|
|
|
|
-- function P:Scale(uiUnitSize)
|
|
|
|
|
-- if uiUnitSize == 0 then
|
|
|
|
|
-- return 0
|
|
|
|
|
-- end
|
|
|
|
|
|
|
|
|
|
-- local uiUnitFactor = PixelUtil.GetPixelToUIUnitFactor()
|
|
|
|
|
-- local numPixels = Round((uiUnitSize * effectiveScale) / uiUnitFactor)
|
|
|
|
|
-- if uiUnitSize < 0.0 then
|
|
|
|
|
-- if numPixels > -1 then
|
|
|
|
|
-- numPixels = -1
|
|
|
|
|
-- end
|
|
|
|
|
-- else
|
|
|
|
|
-- if numPixels < 1 then
|
|
|
|
|
-- numPixels = 1
|
|
|
|
|
-- end
|
|
|
|
|
-- end
|
|
|
|
|
|
|
|
|
|
-- return numPixels * uiUnitFactor / effectiveScale
|
|
|
|
|
-- end
|
|
|
|
|
|
|
|
|
|
--------------------------------------------
|
|
|
|
|
-- some are stolen from ElvUI
|
|
|
|
|
--------------------------------------------
|
|
|
|
|
-- local function GetUIParentScale()
|
|
|
|
|
-- local scale = UIParent:GetScale()
|
|
|
|
|
-- return scale - scale % 0.1 ^ 2
|
|
|
|
|
-- end
|
|
|
|
|
|
|
|
|
|
local mult = 1
|
|
|
|
|
function P:SetRelativeScale(scale)
|
|
|
|
|
mult = 1 / scale
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function P:GetEffectiveScale()
|
|
|
|
|
return P:GetPixelPerfectScale() / mult
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function P:SetEffectiveScale(frame)
|
|
|
|
|
frame:SetScale(P:GetEffectiveScale())
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--[[
|
|
|
|
|
local trunc = function(s) return s >= 0 and s-s%01 or s-s%-1 end
|
|
|
|
|
local round = function(s) return s >= 0 and s-s%-1 or s-s%01 end
|
|
|
|
|
function P:Scale(n)
|
|
|
|
|
return (mult == 1 or n == 0) and n or ((mult < 1 and trunc(n/mult) or round(n/mult)) * mult)
|
|
|
|
|
end
|
|
|
|
|
]]
|
|
|
|
|
function P:Scale(n)
|
|
|
|
|
if mult == 1 or n == 0 then
|
|
|
|
|
return n
|
|
|
|
|
else
|
|
|
|
|
local x = mult > 1 and mult or -mult
|
|
|
|
|
return n - n % (n < 0 and x or -x)
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function P:Size(frame, width, height)
|
|
|
|
|
frame.width = width
|
|
|
|
|
frame.height = height
|
|
|
|
|
frame:SetSize(P:Scale(width), P:Scale(height))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function P:Width(frame, width)
|
|
|
|
|
frame.width = width
|
|
|
|
|
frame:SetWidth(P:Scale(width))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function P:Height(frame, height)
|
|
|
|
|
frame.height = height
|
|
|
|
|
frame:SetHeight(P:Scale(height))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function P:SetGridSize(region, gridWidth, gridHeight, gridSpacingH, gridSpacingV, columns, rows)
|
|
|
|
|
region._size_grid = true
|
|
|
|
|
region._gridWidth = gridWidth
|
|
|
|
|
region._gridHeight = gridHeight
|
|
|
|
|
region._gridSpacingH = gridSpacingH
|
|
|
|
|
region._gridSpacingV = gridSpacingV
|
|
|
|
|
region._rows = rows
|
|
|
|
|
region._columns = columns
|
|
|
|
|
|
|
|
|
|
if columns == 0 then
|
|
|
|
|
region:SetWidth(0.001)
|
|
|
|
|
else
|
|
|
|
|
region:SetWidth(P:Scale(gridWidth) * columns + P:Scale(gridSpacingH) * (columns - 1))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if rows == 0 then
|
|
|
|
|
region:SetHeight(0.001)
|
|
|
|
|
else
|
|
|
|
|
region:SetHeight(P:Scale(gridHeight) * rows + P:Scale(gridSpacingV) * (rows - 1))
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function P:Point(frame, ...)
|
|
|
|
|
if not frame.points then frame.points = {} end
|
|
|
|
|
local point, anchorTo, anchorPoint, x, y
|
|
|
|
|
|
|
|
|
|
local n = select("#", ...)
|
|
|
|
|
if n == 1 then
|
|
|
|
|
point = ...
|
|
|
|
|
elseif n == 3 and type(select(2, ...)) == "number" then
|
|
|
|
|
point, x, y = ...
|
|
|
|
|
elseif n == 4 then
|
|
|
|
|
point, anchorTo, x, y = ...
|
|
|
|
|
else
|
|
|
|
|
point, anchorTo, anchorPoint, x, y = ...
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
tinsert(frame.points, {point, anchorTo or frame:GetParent(), anchorPoint or point, x or 0, y or 0})
|
|
|
|
|
local n = #frame.points
|
|
|
|
|
frame:SetPoint(frame.points[n][1], frame.points[n][2], frame.points[n][3], P:Scale(frame.points[n][4]), P:Scale(frame.points[n][5]))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function P:ClearPoints(frame)
|
|
|
|
|
frame:ClearAllPoints()
|
|
|
|
|
if frame.points then wipe(frame.points) end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
--------------------------------------------
|
|
|
|
|
-- scale changed
|
|
|
|
|
--------------------------------------------
|
|
|
|
|
function P:Resize(frame)
|
|
|
|
|
if frame._size_grid then
|
|
|
|
|
P:SetGridSize(frame, frame._gridWidth, frame._gridHeight, frame._gridSpacingH, frame._gridSpacingV, frame._columns, frame._rows)
|
|
|
|
|
else
|
|
|
|
|
if frame.width then
|
|
|
|
|
frame:SetWidth(P:Scale(frame.width))
|
|
|
|
|
end
|
|
|
|
|
if frame.height then
|
|
|
|
|
frame:SetHeight(P:Scale(frame.height))
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function P:Reborder(frame)
|
|
|
|
|
if not frame.backdropInfo then return end
|
|
|
|
|
|
|
|
|
|
local _r, _g, _b, _a = frame:GetBackdropColor()
|
|
|
|
|
local r, g, b, a = frame:GetBackdropBorderColor()
|
|
|
|
|
|
|
|
|
|
frame.backdropInfo.edgeSize = P:Scale(CELL_BORDER_SIZE or 1)
|
|
|
|
|
frame:ApplyBackdrop()
|
|
|
|
|
|
|
|
|
|
if _r then frame:SetBackdropColor(_r, _g, _b, _a) end
|
|
|
|
|
if r then frame:SetBackdropBorderColor(r, g, b, a) end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function P:Repoint(frame)
|
|
|
|
|
if not frame.points or #frame.points == 0 then return end
|
|
|
|
|
frame:ClearAllPoints()
|
|
|
|
|
for _, t in pairs(frame.points) do
|
|
|
|
|
frame:SetPoint(t[1], t[2], t[3], P:Scale(t[4]), P:Scale(t[5]))
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
-- local frames = {}
|
|
|
|
|
-- function P:SetPixelPerfect(frame)
|
|
|
|
|
-- tinsert(frames, frame)
|
|
|
|
|
-- end
|
|
|
|
|
|
|
|
|
|
-- function P:UpdatePixelPerfectFrames()
|
|
|
|
|
-- for _, f in pairs(frames) do
|
|
|
|
|
-- f:UpdatePixelPerfect()
|
|
|
|
|
-- end
|
|
|
|
|
-- end
|
|
|
|
|
|
|
|
|
|
--------------------------------------------
|
|
|
|
|
-- save & load position
|
|
|
|
|
--------------------------------------------
|
|
|
|
|
function P:SavePosition(frame, positionTable)
|
|
|
|
|
wipe(positionTable)
|
|
|
|
|
local left = math.floor(frame:GetLeft() + 0.5)
|
|
|
|
|
local top = math.floor(frame:GetTop() + 0.5)
|
|
|
|
|
positionTable[1], positionTable[2] = left, top
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function P:LoadPosition(frame, positionTable)
|
|
|
|
|
if type(positionTable) ~= "table" or #positionTable ~= 2 then return end
|
|
|
|
|
|
|
|
|
|
P:ClearPoints(frame)
|
|
|
|
|
P:Point(frame, "TOPLEFT", UIParent, "BOTTOMLEFT", positionTable[1], positionTable[2])
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
---------------------------------------------------------------------
|
|
|
|
|
-- pixel perfect (ElvUI)
|
|
|
|
|
---------------------------------------------------------------------
|
|
|
|
|
local function CheckPixelSnap(frame, snap)
|
|
|
|
|
if (frame and not frame:IsForbidden()) and frame.PixelSnapDisabled and snap then
|
|
|
|
|
frame.PixelSnapDisabled = nil
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function DisablePixelSnap(frame)
|
|
|
|
|
if (frame and not frame:IsForbidden()) and not frame.PixelSnapDisabled then
|
|
|
|
|
if frame.SetSnapToPixelGrid then
|
|
|
|
|
frame:SetSnapToPixelGrid(false)
|
|
|
|
|
frame:SetTexelSnappingBias(0)
|
|
|
|
|
frame.PixelSnapDisabled = true
|
|
|
|
|
elseif frame.GetStatusBarTexture then
|
|
|
|
|
local texture = frame:GetStatusBarTexture()
|
|
|
|
|
if type(texture) == "table" and texture.SetSnapToPixelGrid then
|
|
|
|
|
texture:SetSnapToPixelGrid(false)
|
|
|
|
|
texture:SetTexelSnappingBias(0)
|
|
|
|
|
frame.PixelSnapDisabled = true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local function UpdateMetatable(obj)
|
|
|
|
|
local t = getmetatable(obj).__index
|
|
|
|
|
|
|
|
|
|
if not obj.DisabledPixelSnap and (t.SetSnapToPixelGrid or t.SetStatusBarTexture or t.SetColorTexture or t.SetVertexColor or t.CreateTexture or t.SetTexCoord or t.SetTexture) then
|
|
|
|
|
if t.SetSnapToPixelGrid then hooksecurefunc(t, "SetSnapToPixelGrid", CheckPixelSnap) end
|
|
|
|
|
if t.SetStatusBarTexture then hooksecurefunc(t, "SetStatusBarTexture", DisablePixelSnap) end
|
|
|
|
|
if t.SetColorTexture then hooksecurefunc(t, "SetColorTexture", DisablePixelSnap) end
|
|
|
|
|
if t.SetVertexColor then hooksecurefunc(t, "SetVertexColor", DisablePixelSnap) end
|
|
|
|
|
if t.CreateTexture then hooksecurefunc(t, "CreateTexture", DisablePixelSnap) end
|
|
|
|
|
if t.SetTexCoord then hooksecurefunc(t, "SetTexCoord", DisablePixelSnap) end
|
|
|
|
|
if t.SetTexture then hooksecurefunc(t, "SetTexture", DisablePixelSnap) end
|
|
|
|
|
|
|
|
|
|
t.DisabledPixelSnap = true
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
local obj = CreateFrame("Frame")
|
|
|
|
|
UpdateMetatable(CreateFrame("StatusBar"))
|
|
|
|
|
UpdateMetatable(obj:CreateTexture())
|
|
|
|
|
UpdateMetatable(obj:CreateMaskTexture())
|