diff --git a/api/api.lua b/api/api.lua
index 0405b00d..e2850c1a 100644
--- a/api/api.lua
+++ b/api/api.lua
@@ -992,28 +992,53 @@ function pfUI.api.GetBorderSize(pref)
end
end
+-- The scale UIParent ends up with: one UI unit per screen pixel when pixel
+-- perfect, else the game's own. The game applies its scale only after the
+-- add-ons and their saved variables are loaded (CGGameUI::Initialize ends in
+-- OnDisplaySizeChanged), so at load time it is worked out from the same
+-- options and rules: uiScale while useUiScale is on and it is at least 0.64,
+-- else 768 over the window height kept within 0.9 and 1. Windows narrower
+-- than 4:3 cap either at 3/4 of their aspect.
+local function GetUIScale()
+ if pfUI_config.global.pixelperfect == "1" then return PixelUtil.GetPixelToUIUnitFactor() end
+
+ local width, height = GetPhysicalScreenSize()
+ local aspect = GetCVar("widescreen") == "1" and width / height or 4/3
+ local function fit(scale)
+ return aspect < 4/3 and math.min(scale, aspect * .75) or scale
+ end
+
+ if GetCVar("useUiScale") == "1" then
+ local scale = fit(tonumber(GetCVar("uiScale")))
+ if scale >= .64 then return scale end
+ end
+
+ return math.max(fit(height > 768 and 768 / height or 1), .9)
+end
+
+-- [ UpdateUIScale ]
+-- Gives UIParent the pixel perfect scale when enabled, else leaves the game's
+-- own. The engine puts its own scale back on every window resize and scale
+-- option change, so this runs again on each UI_SCALE_CHANGED. Borders keep
+-- the pixel size they were built with, so a change of it offers a reload once.
+function pfUI.api.UpdateUIScale()
+ if pfUI_config.global.pixelperfect == "1" then
+ UIParent:SetScale(PixelUtil.GetPixelToUIUnitFactor())
+ end
+
+ if not pfUI.pixel or pfUI.scaleprompt then return end
+ if math.abs(PixelUtil.GetPixelToUIUnitFactor() / UIParent:GetScale() - pfUI.pixel) < .0001 then return end
+
+ pfUI.scaleprompt = true
+ CreateQuestionDialog(T["The UI-Scale has changed. Reload the UI to redraw the borders?"], ReloadUI)
+end
+
-- [ GetPerfectPixel ]
--- Returns a number that equals a real pixel on regular scaled frames.
--- Respects the current UI-scale and calculates a real pixel based on
--- the screen resolution and the 768px sized drawlayer.
+-- Returns the size of one physical pixel in UIParent units.
function pfUI.api.GetPerfectPixel()
if pfUI.pixel then return pfUI.pixel end
- if pfUI_config.appearance.border.pixelperfect == "1" then
- local scale = GetCVar("useUiScale") == "1" and GetCVar("uiScale") or "1"
- local resolution = GetCVar("gxResolution")
- local _, _, screenwidth, screenheight = strfind(resolution, "(.+)x(.+)")
-
- pfUI.pixel = 768 / screenheight / scale
- pfUI.pixel = pfUI.pixel > 1 and 1 or pfUI.pixel
-
- -- autodetect and zoom for HiDPI displays
- if pfUI_config.appearance.border.hidpi == "1" then
- pfUI.pixel = pfUI.pixel < .5 and pfUI.pixel * 2 or pfUI.pixel
- end
- else
- pfUI.pixel = .7
- end
+ pfUI.pixel = PixelUtil.GetPixelToUIUnitFactor() / GetUIScale()
pfUI.backdrop = {
bgFile = "Interface\\BUTTONS\\WHITE8X8", tile = false, tileSize = 0,
diff --git a/api/config.lua b/api/config.lua
index 8987796c..5ee3ead3 100644
--- a/api/config.lua
+++ b/api/config.lua
@@ -129,9 +129,7 @@ function pfUI:LoadConfig()
pfUI:UpdateConfig("appearance", "border", "color", "0.2,0.2,0.2,1")
pfUI:UpdateConfig("appearance", "border", "shadow", "0")
pfUI:UpdateConfig("appearance", "border", "shadow_intensity", ".35")
- pfUI:UpdateConfig("appearance", "border", "pixelperfect", "1")
pfUI:UpdateConfig("appearance", "border", "force_blizz", "0")
- pfUI:UpdateConfig("appearance", "border", "hidpi", "1")
pfUI:UpdateConfig("appearance", "border", "default", "3")
pfUI:UpdateConfig("appearance", "border", "nameplates", "-1")
pfUI:UpdateConfig("appearance", "border", "actionbars", "-1")
diff --git a/init/modules.xml b/init/modules.xml
index febafbdc..bfb2ece6 100644
--- a/init/modules.xml
+++ b/init/modules.xml
@@ -54,7 +54,6 @@
-
diff --git a/modules/firstrun.lua b/modules/firstrun.lua
index 072d408e..1f5c46e2 100644
--- a/modules/firstrun.lua
+++ b/modules/firstrun.lua
@@ -136,17 +136,19 @@ pfUI:RegisterModule("firstrun", function ()
local f = CreateFirstRunPage()
f.text:SetText(T["A new installation of |cff33ffccpf|rUI ships with 4 prebuilt design profiles. Click below if you wish to load one of these profiles."])
+ local function LoadProfile(name)
+ _G["pfUI_config"] = CopyTable(pfUI_profiles[name])
+ pfUI_init.selected_profile = name
+ pfUI:LoadConfig()
+ ReloadUI()
+ end
+
f.Modern = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
f.Modern:SetSize(120, 20)
f.Modern:SetPoint("BOTTOM", -65, 100)
f.Modern:SetTextColor(1,1,1)
f.Modern:SetText("Modern")
- f.Modern:SetScript("OnClick", function()
- _G["pfUI_config"] = CopyTable(pfUI_profiles["Modern"])
- pfUI_init.selected_profile = "Modern"
- pfUI:LoadConfig()
- ReloadUI()
- end)
+ f.Modern:SetScript("OnClick", function() LoadProfile("Modern") end)
SkinButton(f.Modern)
f.Nostalgia = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
@@ -154,12 +156,7 @@ pfUI:RegisterModule("firstrun", function ()
f.Nostalgia:SetPoint("BOTTOM", 65, 100)
f.Nostalgia:SetTextColor(1,1,1)
f.Nostalgia:SetText("Nostalgia")
- f.Nostalgia:SetScript("OnClick", function()
- _G["pfUI_config"] = CopyTable(pfUI_profiles["Nostalgia"])
- pfUI_init.selected_profile = "Nostalgia"
- pfUI:LoadConfig()
- ReloadUI()
- end)
+ f.Nostalgia:SetScript("OnClick", function() LoadProfile("Nostalgia") end)
SkinButton(f.Nostalgia)
f.Legacy = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
@@ -167,12 +164,7 @@ pfUI:RegisterModule("firstrun", function ()
f.Legacy:SetPoint("BOTTOM", 65, 75)
f.Legacy:SetTextColor(1,1,1)
f.Legacy:SetText("Legacy")
- f.Legacy:SetScript("OnClick", function()
- _G["pfUI_config"] = CopyTable(pfUI_profiles["Legacy"])
- pfUI_init.selected_profile = "Legacy"
- pfUI:LoadConfig()
- ReloadUI()
- end)
+ f.Legacy:SetScript("OnClick", function() LoadProfile("Legacy") end)
SkinButton(f.Legacy)
f.Slim = CreateFrame("Button", nil, f, "UIPanelButtonTemplate")
@@ -180,12 +172,7 @@ pfUI:RegisterModule("firstrun", function ()
f.Slim:SetPoint("BOTTOM", -65, 75)
f.Slim:SetTextColor(1,1,1)
f.Slim:SetText("Slim")
- f.Slim:SetScript("OnClick", function()
- _G["pfUI_config"] = CopyTable(pfUI_profiles["Slim"])
- pfUI_init.selected_profile = "Slim"
- pfUI:LoadConfig()
- ReloadUI()
- end)
+ f.Slim:SetScript("OnClick", function() LoadProfile("Slim") end)
SkinButton(f.Slim)
f.Slider = CreateFrame("Slider", "pfFirstRunWizardScaleSlider", f, "OptionsSliderTemplate")
@@ -196,14 +183,14 @@ pfUI:RegisterModule("firstrun", function ()
f.Slider:SetSize(240, 20)
f.Slider:SetPoint("BOTTOM", 0, 50)
f.Slider:SetOrientation('HORIZONTAL')
- f.Slider:SetMinMaxValues(0.5, 2.0)
+ -- the game drops a uiScale under 0.64 for its automatic scale at login
+ f.Slider:SetMinMaxValues(0.64, 2.0)
f.Slider:SetValue(UIParent:GetScale())
f.Slider:SetScript("OnMouseUp", function()
local scale = round(this:GetValue(),2)
SetCVar("uiScale", scale)
SetCVar("useUiScale", 1)
- UIParent:SetScale(scale)
this:SetValue(scale)
end)
diff --git a/modules/gui.lua b/modules/gui.lua
index 77a325b7..03397952 100644
--- a/modules/gui.lua
+++ b/modules/gui.lua
@@ -130,7 +130,7 @@ pfUI:RegisterModule("gui", function ()
category = {}
category[config] = tostring(GetCVar(config))
ufunc = function()
- SetCVar(this:GetParent().config, this:GetParent().category[config])
+ SetCVar(config, category[config])
end
end
@@ -881,14 +881,6 @@ pfUI:RegisterModule("gui", function ()
"35:35",
"40:40",
},
- ["scaling"] = {
- "0:" .. T["Off"],
- "4:" .. T["Huge (PixelPerfect)"],
- "5:" .. T["Large"],
- "6:" .. T["Medium"],
- "7:" .. T["Small"],
- "8:" .. T["Tiny (PixelPerfect)"],
- },
["abbrevnum"] = {
"0:" .. T["Full Numbers (4250)"],
"1:" .. T["Abbreviate 2 Decimals (4.25k)"],
@@ -1508,7 +1500,24 @@ pfUI:RegisterModule("gui", function ()
CreateConfig(nil, T["Settings"], nil, nil, "header")
CreateConfig(nil, T["Language"], C.global, "language", "dropdown", pfUI.gui.dropdowns.languages)
- CreateConfig(U["pixelperfect"], T["Enable UI-Scale"], C.global, "pixelperfect", "dropdown", pfUI.gui.dropdowns.scaling)
+ -- the game's own scale options, as in its Video Options; the list keeps
+ -- a value set there that is none of these steps
+ CreateConfig(nil, T["Use UI-Scale"], "CVAR", "useUiScale", "checkbox")
+ CreateConfig(nil, T["UI-Scale"], "CVAR", "uiScale", "dropdown", function()
+ local current = GetCVar("uiScale")
+ local values, found = {}, nil
+ for _, scale in ipairs({ .64, .65, .7, .75, .8, .85, .9, .95, 1, 1.1, 1.2, 1.3, 1.4, 1.5 }) do
+ if math.abs(scale - tonumber(current)) < .001 then
+ found = true
+ table.insert(values, current .. ":" .. scale)
+ else
+ table.insert(values, tostring(scale))
+ end
+ end
+ if not found then table.insert(values, 1, current .. ":" .. round(tonumber(current), 2)) end
+ return values
+ end)
+ CreateConfig(nil, string.format(T["Pixel Perfect UI-Scale: %s (Overrides UI-Scale)"], round(PixelUtil.GetPixelToUIUnitFactor(), 2)), C.global, "pixelperfect", "checkbox")
CreateConfig(nil, T["Use Original Game Fonts"], C.global, "font_blizzard", "checkbox")
CreateConfig(nil, T["Enable Region Compatible Font"], C.global, "force_region", "checkbox")
CreateConfig(nil, T["Standard Text Font"], C.global, "font_default", "dropdown", pfUI.gui.dropdowns.fonts)
@@ -1585,8 +1594,6 @@ pfUI:RegisterModule("gui", function ()
CreateConfig(nil, T["Frame Shadow Intensity"], C.appearance.border, "shadow_intensity", "dropdown", pfUI.gui.dropdowns.uf_debuff_indicator_size)
CreateConfig(nil) -- spacer
CreateConfig(nil, T["Force Blizzard Borders (|cffffaaaaExperimental|r)"], C.appearance.border, "force_blizz", "checkbox")
- CreateConfig(nil, T["Enable Pixel Perfect Borders"], C.appearance.border, "pixelperfect", "checkbox")
- CreateConfig(nil, T["Scale Border On HiDPI Displays"], C.appearance.border, "hidpi", "checkbox")
CreateConfig(nil) -- spacer
CreateConfig(nil, T["Global Border Size"], C.appearance.border, "default", "dropdown", pfUI.gui.dropdowns.border)
CreateConfig(nil, T["Action Bar Border Size"], C.appearance.border, "actionbars", "dropdown", pfUI.gui.dropdowns.border)
diff --git a/modules/pixelperfect.lua b/modules/pixelperfect.lua
deleted file mode 100644
index 872b5d37..00000000
--- a/modules/pixelperfect.lua
+++ /dev/null
@@ -1,43 +0,0 @@
-pfUI:RegisterModule("pixelperfect", function ()
- -- pre-calculated min values
- local statics = {
- [4] = 1.4222222222222,
- [5] = 1.1377777777778,
- [6] = 0.94814814814815,
- [7] = 0.81269841269841,
- [8] = 0.71111111111111,
- }
-
- -- pixel perfect
- local function pixelperfect()
- local conf = tonumber(C.global.pixelperfect)
- if conf < 4 then
- -- restore gamesettings
- local scale = GetCVar("uiScale")
- local use = GetCVar("useUiScale")
-
- if use == 1 then
- UIParent:SetScale(tonumber(use))
- else
- UIParent:SetScale(.9)
- end
- else
- local scale = conf and statics[conf] or 1
-
- SetCVar("uiScale", scale)
- SetCVar("useUiScale", 1)
-
- UIParent:SetScale(scale)
- end
- end
-
- -- pixelperfect: native UIScale listener
- if tonumber(C.global.pixelperfect) > 0 then
- pfUI.events:RegisterFrameEventAndCallback("PLAYER_ENTERING_WORLD", pixelperfect)
- pixelperfect()
- end
-
- pfUI.pixelperfect = {
- UpdateConfig = pixelperfect
- }
-end)
diff --git a/pfUI.lua b/pfUI.lua
index 6b1fe21d..ea9d3d0d 100644
--- a/pfUI.lua
+++ b/pfUI.lua
@@ -392,6 +392,10 @@ pfUI:SetScript("OnEvent", function()
SetupConfigEnvironment()
pfUI:UpdateFonts()
+ -- scale UIParent before the modules size their borders from it
+ pfUI.api.UpdateUIScale()
+ pfUI.events:RegisterFrameEventAndCallback("UI_SCALE_CHANGED", pfUI.api.UpdateUIScale)
+
-- load modules
for _, m in pairs(this.modules) do
if not ( pfUI_config["disabled"] and pfUI_config["disabled"][m] == "1" ) then