You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

381 lines
11 KiB

--------------------------------------------
-- http://wow.gamepedia.com/UI_Scale
-- http://www.wowinterface.com/forums/showthread.php?t=31813
--------------------------------------------
5 months ago
local _, addon = ...
addon.pixelPerfectFuncs = {}
5 months ago
local function Round(num, numDecimalPlaces)
if numDecimalPlaces and numDecimalPlaces >= 0 then
local mult = 10 ^ numDecimalPlaces
num = num * mult
if num >= 0 then
return floor(num + 0.5) / mult
else
return ceil(num - 0.5) / mult
end
end
if num >= 0 then
return floor(num + 0.5)
else
return ceil(num - 0.5)
end
end
local Clamp = Clamp
---@class PixelPerfectFuncs
local P = addon.pixelPerfectFuncs
5 months ago
function P.GetResolution()
-- return string.match(({GetScreenResolutions()})[GetCurrentResolution()], "(%d+)x(%d+)")
return GetPhysicalScreenSize()
end
5 months ago
-- 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.
5 months ago
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
5 months ago
function P.GetRecommendedScale()
local pScale = P.GetPixelPerfectScale()
local mult
if pScale >= 0.71 then -- 1080
mult = 1
elseif pScale >= 0.53 then -- 1440
mult = 1.2
else -- 2160
mult = 1.7
end
return Clamp(Round(pScale / UIParent:GetScale() * mult, 2), 0.5, 2)
end
-- scale perfect!
5 months ago
function P.PixelPerfectScale(frame)
frame:SetScale(P.GetPixelPerfectScale())
end
-- position perfect!
5 months ago
function P.PixelPerfectPoint(frame)
local left = frame:GetLeft()
local top = frame:GetTop()
frame:ClearAllPoints()
5 months ago
frame:SetPoint("TOPLEFT", CellParent, "BOTTOMLEFT", math.floor(left + 0.5), math.floor(top + 0.5))
end
--------------------------------------------
-- PixelUtil
--------------------------------------------
-- local effectiveScale = 1
5 months ago
-- function P.SetRelativeScale(scale)
-- effectiveScale = scale
-- end
5 months ago
-- function P.GetEffectiveScale()
-- return effectiveScale
-- end
5 months ago
-- function P.SetEffectiveScale(frame)
-- frame:SetScale(effectiveScale)
-- end
5 months ago
-- 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
5 months ago
local scale = 1
local mult = 1
5 months ago
---@deprecated
function P.SetRelativeScale(s)
mult = 1 / s
scale = s
end
5 months ago
---@deprecated
function P.GetEffectiveScale()
return P.GetPixelPerfectScale() / mult
end
5 months ago
---@deprecated
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
5 months ago
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
]]
5 months ago
-- 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
local GetNearestPixelSize = PixelUtil.GetNearestPixelSize
function P.Scale(desiredPixels)
return GetNearestPixelSize(desiredPixels, CellParent:GetEffectiveScale())
end
5 months ago
function P.Size(frame, width, height)
frame.width = width
frame.height = height
5 months ago
frame:SetSize(P.Scale(width), P.Scale(height))
end
5 months ago
function P.Width(frame, width)
frame.width = width
5 months ago
frame:SetWidth(P.Scale(width))
end
5 months ago
function P.Height(frame, height)
frame.height = height
5 months ago
frame:SetHeight(P.Scale(height))
end
5 months ago
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
5 months ago
region:SetWidth(P.Scale(gridWidth) * columns + P.Scale(gridSpacingH) * (columns - 1))
end
if rows == 0 then
region:SetHeight(0.001)
else
5 months ago
region:SetHeight(P.Scale(gridHeight) * rows + P.Scale(gridSpacingV) * (rows - 1))
end
end
5 months ago
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
5 months ago
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
5 months ago
function P.ClearPoints(frame)
frame:ClearAllPoints()
if frame.points then wipe(frame.points) end
end
--------------------------------------------
-- scale changed
--------------------------------------------
5 months ago
function P.Resize(frame)
if frame._size_grid then
5 months ago
P.SetGridSize(frame, frame._gridWidth, frame._gridHeight, frame._gridSpacingH, frame._gridSpacingV, frame._columns, frame._rows)
else
if frame.width then
5 months ago
frame:SetWidth(P.Scale(frame.width))
end
if frame.height then
5 months ago
frame:SetHeight(P.Scale(frame.height))
end
end
end
5 months ago
function P.Reborder(frame, ignoreSnippetVar)
if not frame.backdropInfo then return end
local _r, _g, _b, _a = frame:GetBackdropColor()
local r, g, b, a = frame:GetBackdropBorderColor()
if ignoreSnippetVar then
5 months ago
frame.backdropInfo.edgeSize = P.Scale(1)
else
if CELL_BORDER_SIZE == 0 then
frame.backdropInfo.edgeFile = nil
frame.backdropInfo.edgeSize = nil
else
5 months ago
frame.backdropInfo.edgeSize = P.Scale(CELL_BORDER_SIZE or 1)
end
end
frame:ApplyBackdrop()
if _r then frame:SetBackdropColor(_r, _g, _b, _a) end
if r then frame:SetBackdropBorderColor(r, g, b, a) end
end
5 months ago
function P.Repoint(frame)
if not frame.points or #frame.points == 0 then return end
frame:ClearAllPoints()
for _, t in pairs(frame.points) do
5 months ago
frame:SetPoint(t[1], t[2], t[3], P.Scale(t[4]), P.Scale(t[5]))
end
end
-- local frames = {}
5 months ago
-- function P.SetPixelPerfect(frame)
-- tinsert(frames, frame)
-- end
5 months ago
-- function P.UpdatePixelPerfectFrames()
-- for _, f in pairs(frames) do
-- f:UpdatePixelPerfect()
-- end
-- end
--------------------------------------------
-- save & load position
--------------------------------------------
5 months ago
function P.SavePosition(frame, positionTable)
wipe(positionTable)
5 months ago
positionTable[1], positionTable[2], positionTable[3] = P.CalcPoint(frame)
-- 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" then return end
if #positionTable == 2 then
P.ClearPoints(frame)
P.Point(frame, "TOPLEFT", UIParent, "BOTTOMLEFT", positionTable[1], positionTable[2])
return true
elseif #positionTable == 3 then
P.ClearPoints(frame)
frame:SetPoint(positionTable[1], CellParent, positionTable[2], positionTable[3])
return true
end
end
5 months ago
function P.CalcPoint(frame)
local point, x, y
local centerX, centerY = CellParent:GetCenter()
local width = CellParent:GetRight()
x, y = frame:GetCenter()
if y >= centerY then
point = "TOP"
y = -(CellParent:GetTop() - frame:GetTop())
else
point = "BOTTOM"
y = frame:GetBottom()
end
if x >= (width * 2 / 3) then
point = point.."RIGHT"
x = frame:GetRight() - width
elseif x <= (width / 3) then
point = point.."LEFT"
x = frame:GetLeft()
else
x = x - centerX
end
-- x = tonumber(string.format("%.2f", x))
-- y = tonumber(string.format("%.2f", y))
x = Round(x, 1)
y = Round(y, 1)
5 months ago
return point, x, y
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())