147 lines
5.8 KiB
Lua
147 lines
5.8 KiB
Lua
local A = OctoQuestRewards
|
|
local G = getfenv(0)
|
|
local panels = {
|
|
detail = { "QuestFrameDetailPanel", "QuestDetailScrollChildFrame", "QuestDetailScrollFrame", "QuestDescription", "QuestDetailRewardTitleText" },
|
|
progress = { "QuestFrameProgressPanel", "QuestProgressScrollChildFrame", "QuestProgressScrollFrame", "QuestProgressText" },
|
|
reward = { "QuestFrameRewardPanel", "QuestRewardScrollChildFrame", "QuestRewardScrollFrame", "QuestRewardText", "QuestRewardRewardTitleText" },
|
|
log = { "QuestLogFrame", "QuestLogDetailScrollChildFrame", "QuestLogDetailScrollFrame", "QuestLogQuestDescription", "QuestLogRewardTitleText" },
|
|
}
|
|
|
|
-- Copy the live font, including addon overrides, rather than just its template.
|
|
local function CopyFont(target, source)
|
|
if not source or not source.GetFont then return end
|
|
local font, size, flags = source:GetFont()
|
|
if font and size then target:SetFont(font, size, flags or "") end
|
|
end
|
|
|
|
function A.Number(value)
|
|
local s = tostring(math.floor(value))
|
|
local count
|
|
repeat s, count = string.gsub(s, "^(%-?%d+)(%d%d%d)", "%1,%2") until count == 0
|
|
return s
|
|
end
|
|
|
|
function A.Money(copper)
|
|
copper = math.floor(copper)
|
|
local gold = math.floor(copper / 10000)
|
|
local silver = math.floor(copper / 100) - gold * 100
|
|
local coins = copper - math.floor(copper / 100) * 100
|
|
local parts = {}
|
|
if gold > 0 then table.insert(parts, gold .. "g") end
|
|
if silver > 0 then table.insert(parts, silver .. "s") end
|
|
if coins > 0 then table.insert(parts, coins .. "c") end
|
|
return table.concat(parts, " ")
|
|
end
|
|
|
|
-- Read actual visible content extents, including the nested fading reward area.
|
|
-- Ignore textures and spacer frames, whose bounds aren't content bounds.
|
|
local function ContentBottom(object, block, top, scale, depth)
|
|
if object == block or not object:IsShown() or depth > 5 then return 0 end
|
|
local name = object:GetName() or ""
|
|
if string.find(name, "Spacer") then return 0 end
|
|
local bottom = 0
|
|
local isText = object:IsObjectType("FontString")
|
|
if (isText and object:GetText() and object:GetText() ~= "")
|
|
or object:IsObjectType("Button") or string.find(name, "MoneyFrame$") then
|
|
local b = object:GetBottom()
|
|
if b then
|
|
-- FontStrings inherit their parent's scale; don't assume Frame-only
|
|
-- methods exist on Vanilla regions.
|
|
local owner = isText and object:GetParent() or object
|
|
bottom = (top * scale - b * owner:GetEffectiveScale()) / scale
|
|
end
|
|
end
|
|
if object.GetRegions then
|
|
for _, region in ipairs({object:GetRegions()}) do
|
|
bottom = math.max(bottom, ContentBottom(region, block, top, scale, depth + 1))
|
|
end
|
|
end
|
|
if object.GetChildren then
|
|
for _, child in ipairs({object:GetChildren()}) do
|
|
bottom = math.max(bottom, ContentBottom(child, block, top, scale, depth + 1))
|
|
end
|
|
end
|
|
return bottom
|
|
end
|
|
|
|
function A.Render(kind)
|
|
local cfg = panels[kind]
|
|
local panel, child, scroll = G[cfg[1]], G[cfg[2]], G[cfg[3]]
|
|
if not panel or not child or not scroll then return end
|
|
if cfg.block then cfg.block:Hide() end
|
|
if not panel:IsVisible() then return end
|
|
local r = A.GetRecord(kind)
|
|
A.current = r
|
|
if A.db.debug and r then A.DebugRecord(r) end
|
|
local lines = {}
|
|
if r and r.xp and r.xp > 0 then table.insert(lines, "Estimated XP: " .. A.Number(r.xp)) end
|
|
if not cfg.block then
|
|
cfg.block = CreateFrame("Frame", nil, child)
|
|
cfg.block:SetWidth(child:GetWidth() - 15)
|
|
cfg.block.title = cfg.block:CreateFontString(nil, "ARTWORK", "QuestTitleFont")
|
|
cfg.block.title:SetPoint("TOPLEFT", cfg.block, "TOPLEFT", 0, 0)
|
|
cfg.block.title:SetText("Rewards")
|
|
cfg.block.text = cfg.block:CreateFontString(nil, "ARTWORK", "QuestFont")
|
|
cfg.block.text:SetJustifyH("LEFT")
|
|
cfg.baseHeight = child:GetHeight()
|
|
end
|
|
local block = cfg.block
|
|
-- Keep our previous extension out of the next layout calculation.
|
|
if cfg.lastHeight and child:GetHeight() == cfg.lastHeight then child:SetHeight(cfg.baseHeight) end
|
|
if table.getn(lines) == 0 then
|
|
block:Hide()
|
|
scroll:UpdateScrollChildRect()
|
|
return
|
|
end
|
|
local top, scale = child:GetTop(), child:GetEffectiveScale()
|
|
if not top then block:Hide(); return end
|
|
local bottom = ContentBottom(child, block, top, scale, 0)
|
|
local heading = cfg[5] and G[cfg[5]]
|
|
local example = G[cfg[4]]
|
|
CopyFont(block.text, example)
|
|
CopyFont(block.title, heading or G.QuestProgressTitleText)
|
|
local titleHeight = 0
|
|
if heading and heading:IsShown() then block.title:Hide()
|
|
else
|
|
block.title:Show()
|
|
titleHeight = block.title:GetHeight() + 5
|
|
end
|
|
block:ClearAllPoints()
|
|
block:SetPoint("TOPLEFT", child, "TOPLEFT", 5, -bottom - 12)
|
|
block:SetWidth(child:GetWidth() - 15)
|
|
block.text:ClearAllPoints()
|
|
block.text:SetPoint("TOPLEFT", block, "TOPLEFT", 0, -titleHeight)
|
|
block.text:SetWidth(block:GetWidth())
|
|
block.text:SetText(table.concat(lines, "\n"))
|
|
if example and example.GetTextColor then
|
|
block.text:SetTextColor(example:GetTextColor())
|
|
else block.text:SetTextColor(0, 0, 0) end
|
|
if heading and heading.GetTextColor then block.title:SetTextColor(heading:GetTextColor()) end
|
|
block:SetHeight(titleHeight + block.text:GetHeight())
|
|
cfg.lastHeight = math.max(cfg.baseHeight, bottom + 12 + block:GetHeight() + 12)
|
|
child:SetHeight(cfg.lastHeight)
|
|
block:Show()
|
|
scroll:UpdateScrollChildRect()
|
|
end
|
|
|
|
function A.RenderAll()
|
|
for kind in pairs(panels) do A.Render(kind) end
|
|
end
|
|
|
|
function A.HookScript(frame, script, callback)
|
|
if not frame then return end
|
|
if frame.HookScript then frame:HookScript(script, callback); return end
|
|
-- Vanilla has no HookScript. Chain the existing script with its original args.
|
|
local old = frame:GetScript(script)
|
|
frame:SetScript(script, function(...)
|
|
if old then old(unpack(arg)) end
|
|
callback()
|
|
end)
|
|
end
|
|
|
|
function A.SetupUI()
|
|
for _, cfg in pairs(panels) do
|
|
A.HookScript(G[cfg[1]], "OnShow", A.Schedule)
|
|
end
|
|
end
|