聊天重做前缓存

This commit is contained in:
rucky
2026-04-09 09:46:47 +08:00
parent 6e18269bfd
commit e915bbd74a
39 changed files with 8501 additions and 2308 deletions

View File

@@ -496,20 +496,31 @@ ShowLootPage = function()
row:Show()
end
-- Let the ORIGINAL Blizzard LootFrame_Update run so that native
-- LootButton1-4 get their IDs, slot data, and OnClick set up
-- through the trusted native code path (required for LootSlot).
-- Set up the native LootFrame so it stays alive (required by the
-- engine) but completely invisible. We do NOT call origLootFrameUpdate
-- because it uses a different items-per-page (3 when paginated vs our 4)
-- which mis-calculates slot indices.
if LootFrame then
LootFrame.numLootItems = numItems
LootFrame.page = page
if not LootFrame:IsShown() then LootFrame:Show() end
end
if origLootFrameUpdate then origLootFrameUpdate() end
-- Now reposition the native buttons on top of our visual rows
-- Directly configure native LootButtons with the correct slot for
-- each visual row. SetSlot is the C++ binding that the native
-- LootButton_OnClick / LootFrameItem_OnClick reads via this.slot.
for btnIdx = 1, ITEMS_PER_PAGE do
local nb = _G["LootButton" .. btnIdx]
local row = lootRows[btnIdx]
if nb and row and row:IsShown() and row._qualColor then
local realSlot = row.slotIndex
-- SetSlot is the native C++ method; .slot is the Lua mirror.
if nb.SetSlot then nb:SetSlot(realSlot) end
nb.slot = realSlot
local _, _, _, rq = GetLootSlotInfo(realSlot)
nb.quality = rq or 0
nb:ClearAllPoints()
nb:SetPoint("TOPLEFT", row, "TOPLEFT", 0, 0)
nb:SetPoint("BOTTOMRIGHT", row, "BOTTOMRIGHT", 0, 0)
@@ -521,10 +532,10 @@ ShowLootPage = function()
nb._nanamiRow = row
nb:SetScript("OnEnter", function()
local slot = this:GetID()
if slot then
local s = this.slot
if s then
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
GameTooltip:SetLootItem(slot)
GameTooltip:SetLootItem(s)
if CursorUpdate then CursorUpdate() end
end
local r2 = this._nanamiRow
@@ -724,14 +735,15 @@ local function GetAlertFrame()
return CreateAlertFrame()
end
-- Layout: newest item at bottom (index 1 = oldest = top, last = newest = bottom slot 0)
local function LayoutAlerts()
CreateAlertAnchor()
for i = 1, table.getn(activeAlerts) do
local n = table.getn(activeAlerts)
for i = 1, n do
local af = activeAlerts[i]
if af._fadeState ~= "fading" then
af:ClearAllPoints()
af:SetPoint("BOTTOMLEFT", alertAnchor, "BOTTOMLEFT", 0, (i - 1) * (ALERT_HEIGHT + ALERT_GAP))
end
-- oldest at top, newest at bottom: slot = (n - i)
af:ClearAllPoints()
af:SetPoint("BOTTOMLEFT", alertAnchor, "BOTTOMLEFT", 0, (n - i) * (ALERT_HEIGHT + ALERT_GAP))
end
end
@@ -750,36 +762,15 @@ local function RemoveAlert(frame)
LayoutAlerts()
end
local function StartAlertFade(frame, delay)
frame._fadeState = "waiting"
frame._fadeElapsed = 0
frame._fadeDelay = delay
-- Each alert has its own independent timer; when it expires, just disappear (no float animation)
local function StartAlertTimer(frame, delay)
frame._timerElapsed = 0
frame._timerDelay = delay
frame:SetScript("OnUpdate", function()
this._fadeElapsed = (this._fadeElapsed or 0) + arg1
if this._fadeState == "waiting" then
if this._fadeElapsed >= this._fadeDelay then
this._fadeState = "fading"
this._fadeElapsed = 0
this._baseY = 0
for idx = 1, table.getn(activeAlerts) do
if activeAlerts[idx] == this then
this._baseY = (idx - 1) * (ALERT_HEIGHT + ALERT_GAP)
break
end
end
end
elseif this._fadeState == "fading" then
local p = this._fadeElapsed / ALERT_FADE_DUR
if p >= 1 then
RemoveAlert(this)
else
this:SetAlpha(1 - p)
this:ClearAllPoints()
this:SetPoint("BOTTOMLEFT", alertAnchor, "BOTTOMLEFT",
0, this._baseY + p * ALERT_FLOAT)
end
this._timerElapsed = (this._timerElapsed or 0) + arg1
if this._timerElapsed >= this._timerDelay then
RemoveAlert(this)
end
end)
end
@@ -794,14 +785,15 @@ local function ShowLootAlert(texture, name, quality, quantity, link)
local db = GetDB()
if not db.alertEnable then return end
-- Stack same item: update count and reset timer
for i = 1, table.getn(activeAlerts) do
local af = activeAlerts[i]
if af._itemName == name and af._fadeState == "waiting" then
if af._itemName == name then
af._quantity = (af._quantity or 1) + (quantity or 1)
if af._quantity > 1 then
af.countFS:SetText("x" .. af._quantity)
end
af._fadeElapsed = 0
af._timerElapsed = 0
return
end
end
@@ -815,7 +807,6 @@ local function ShowLootAlert(texture, name, quality, quantity, link)
f._quantity = quantity or 1
f._link = link
-- Set icon texture
local iconTex = texture or "Interface\\Icons\\INV_Misc_QuestionMark"
f.icon:SetTexture(iconTex)
@@ -841,12 +832,12 @@ local function ShowLootAlert(texture, name, quality, quantity, link)
f:SetAlpha(1)
f:Show()
-- New item appended to end of list = bottom position
table.insert(activeAlerts, f)
LayoutAlerts()
local hold = db.alertFadeDelay or ALERT_HOLD
local stagger = table.getn(activeAlerts) * ALERT_STAGGER
StartAlertFade(f, hold + stagger)
StartAlertTimer(f, hold)
end
--------------------------------------------------------------------------------
@@ -1000,8 +991,9 @@ function LD:Initialize()
end
end
-- After the native LootFrame_Update runs (called by the engine or
-- by us), reposition native buttons onto our visual rows.
-- Replace LootFrame_Update: run the original for engine compatibility,
-- then re-apply the correct slot on each native button based on our
-- visual rows (which use ITEMS_PER_PAGE=4, not the native 3-when-paged).
LootFrame_Update = function()
if origLootFrameUpdate then origLootFrameUpdate() end
if not (lootFrame and lootFrame:IsShown()) then return end
@@ -1009,6 +1001,11 @@ function LD:Initialize()
local nb = _G["LootButton" .. i]
local row = lootRows[i]
if nb and row and row:IsShown() and row._qualColor then
local realSlot = row.slotIndex
if realSlot then
if nb.SetSlot then nb:SetSlot(realSlot) end
nb.slot = realSlot
end
nb:ClearAllPoints()
nb:SetPoint("TOPLEFT", row, "TOPLEFT", 0, 0)
nb:SetPoint("BOTTOMRIGHT", row, "BOTTOMRIGHT", 0, 0)