1509 lines
62 KiB
Lua
1509 lines
62 KiB
Lua
-- ItemCollection/SM_ItemCollectionUI.lua
|
||
-- 物品收藏界面实现
|
||
SM_CollectionsDB = SM_CollectionsDB or {}
|
||
|
||
SM_CollectionData.Config = {
|
||
CameraOption = "Classic" -- 默认使用Classic视角
|
||
}
|
||
|
||
SM_ItemCollectionUI = {}
|
||
SM_ItemCollectionUI.buttons = {} -- 存储所有创建的按钮引用
|
||
SM_ItemCollectionUI.currentSelectedModel = nil -- 跟踪当前选中的模型
|
||
SM_ItemCollectionUI.currentPanel = nil -- 存储当前面板引用
|
||
SM_ItemCollectionUI.slotData = {} -- 存储物品槽位数据
|
||
SM_ItemCollectionUI.initialized = false -- 标记是否已经初始化
|
||
SM_ItemCollectionUI.currentSelectedButton = nil -- 跟踪当前选中的按钮
|
||
|
||
-- 分页相关变量
|
||
SM_ItemCollectionUI.currentPage = 1
|
||
SM_ItemCollectionUI.itemsPerPage = 18 -- 每页显示18个物品
|
||
SM_ItemCollectionUI.totalPages = 1
|
||
SM_ItemCollectionUI.pageButtons = {}
|
||
|
||
SM_ItemCollectionUI.lastUpdateTime = 0 -- 上次更新时间
|
||
SM_ItemCollectionUI.CACHE_EXPIRE_TIME = 3600 -- 缓存过期时间(1小时)
|
||
|
||
-- 注册物品获取事件
|
||
function SM_ItemCollectionUI:RegisterItemEvents()
|
||
-- 创建事件处理框架
|
||
if not self.eventFrame then
|
||
self.eventFrame = CreateFrame("Frame")
|
||
self.eventFrame:SetScript("OnEvent", function(self, event, ...)
|
||
if event == "CHAT_MSG_LOOT" then
|
||
SM_ItemCollectionUI:OnLootReceived(...)
|
||
elseif event == "BAG_UPDATE" then
|
||
-- 使用背包更新事件替代ITEM_PUSH
|
||
SM_ItemCollectionUI:OnBagUpdate()
|
||
end
|
||
end)
|
||
end
|
||
|
||
-- 注册相关事件
|
||
self.eventFrame:RegisterEvent("CHAT_MSG_LOOT")
|
||
self.eventFrame:RegisterEvent("BAG_UPDATE")
|
||
end
|
||
|
||
-- 处理物品获取事件
|
||
function SM_ItemCollectionUI:OnLootReceived(msg)
|
||
-- 解析聊天消息中的物品ID
|
||
local itemLink = string.match(msg, "|H(item:[^|]+)|h")
|
||
if itemLink then
|
||
local itemID = string.match(itemLink, "item:(%d+)")
|
||
if itemID then
|
||
-- 延迟一点执行更新,确保服务器数据已同步
|
||
local itemToUpdate = itemID
|
||
local updateFrame = CreateFrame("Frame")
|
||
updateFrame:SetScript("OnUpdate", function(self, elapsed)
|
||
self.elapsed = (self.elapsed or 0) + elapsed
|
||
if self.elapsed >= 0.5 then
|
||
SM_ItemCollectionUI:UpdateItemObtainedStatus(itemToUpdate, true)
|
||
self:SetScript("OnUpdate", nil)
|
||
end
|
||
end)
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 处理背包更新事件
|
||
function SM_ItemCollectionUI:OnBagUpdate()
|
||
-- 检查所有背包中的物品
|
||
for bag = 0, 4 do
|
||
local slots = GetContainerNumSlots(bag)
|
||
for slot = 1, slots do
|
||
local itemLink = GetContainerItemLink(bag, slot)
|
||
if itemLink then
|
||
local itemID = string.match(itemLink, "item:(%d+)")
|
||
if itemID and not self.processedItems then
|
||
self.processedItems = {}
|
||
end
|
||
|
||
-- 避免重复处理同一物品
|
||
if itemID and not self.processedItems[itemID] then
|
||
self.processedItems[itemID] = true
|
||
-- 延迟一点执行更新,确保服务器数据已同步
|
||
local itemToUpdate = itemID
|
||
local updateFrame = CreateFrame("Frame")
|
||
updateFrame:SetScript("OnUpdate", function(self, elapsed)
|
||
self.elapsed = (self.elapsed or 0) + elapsed
|
||
if self.elapsed >= 0.5 then
|
||
SM_ItemCollectionUI:UpdateItemObtainedStatus(itemToUpdate, true)
|
||
self:SetScript("OnUpdate", nil)
|
||
end
|
||
end)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 初始化物品收藏界面
|
||
function SM_ItemCollectionUI:Init()
|
||
-- 只做一次全局声明,绝不重置SM_CollectionsDB或itemCache
|
||
-- 从其他文件加载必要的模块
|
||
if not SM_CollectionData then
|
||
LoadAddOn("SM_CollectionSystem")
|
||
end
|
||
-- 初始化物品槽位数据
|
||
self:InitSlotData()
|
||
|
||
-- 注册物品获取事件
|
||
self:RegisterItemEvents()
|
||
|
||
self.initialized = true
|
||
end
|
||
|
||
-- 添加处理NEW图标的统一函数
|
||
function SM_ItemCollectionUI:HandleNewItemIcon(model, itemID)
|
||
if model and itemID and SM_Collections and SM_Collections.NewItems and SM_Collections.NewItems.item and SM_Collections.NewItems.item[tonumber(itemID)] then
|
||
-- 添加"NEW"标记,如果这是新获得的物品
|
||
if model.itemData and model.itemData.obtained and SM_Collections.NewItems and SM_Collections.NewItems.item and SM_Collections.NewItems.item[tonumber(itemID)] then
|
||
-- 创建NEW图标,使用OVERLAY层的最高级别(7)确保显示在最顶层
|
||
if not model.newTexture then
|
||
local newTexture = model:CreateTexture(nil, "OVERLAY", nil, 7)
|
||
newTexture:SetSize(32, 28)
|
||
newTexture:SetPoint("TOPRIGHT", model, "TOPRIGHT", 10, 10)
|
||
newTexture:SetTexture("Interface\\AddOns\\SM_CollectionSystem\\Textures\\New_Icon")
|
||
-- 确保纹理在最顶层
|
||
newTexture:SetDrawLayer("OVERLAY", 7)
|
||
model.newTexture = newTexture
|
||
else
|
||
model.newTexture:Show()
|
||
-- 确保纹理在最顶层
|
||
model.newTexture:SetDrawLayer("OVERLAY", 7)
|
||
end
|
||
else
|
||
-- 如果不是新物品但存在NEW图标,隐藏它
|
||
if model and model.newTexture then
|
||
model.newTexture:Hide()
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 初始化物品槽位数据
|
||
function SM_ItemCollectionUI:InitSlotData()
|
||
-- 获取物品分类数据
|
||
local MODEL_SLOTS = {
|
||
{ name = "头部", invType = "INVTYPE_HEAD", items = {}, icon = "Interface\\PaperDoll\\UI-PaperDoll-Slot-Head" },
|
||
{ name = "肩部", invType = "INVTYPE_SHOULDER", items = {}, icon = "Interface\\PaperDoll\\UI-PaperDoll-Slot-Shoulder" },
|
||
{ name = "背部", invType = "INVTYPE_CLOAK", items = {}, icon = "Interface\\PaperDoll\\UI-PaperDoll-Slot-Chest" },
|
||
{ name = "胸部", invType = "INVTYPE_CHEST", items = {}, icon = "Interface\\PaperDoll\\UI-PaperDoll-Slot-Chest" },
|
||
{ name = "衬衣", invType = "INVTYPE_BODY", items = {}, icon = "Interface\\PaperDoll\\UI-PaperDoll-Slot-Shirt" },
|
||
{ name = "战袍", invType = "INVTYPE_TABARD", items = {}, icon = "Interface\\PaperDoll\\UI-PaperDoll-Slot-Tabard" },
|
||
{ name = "手腕", invType = "INVTYPE_WRIST", items = {}, icon = "Interface\\PaperDoll\\UI-PaperDoll-Slot-Wrists" },
|
||
{ name = "手", invType = "INVTYPE_HAND", items = {}, icon = "Interface\\PaperDoll\\UI-PaperDoll-Slot-Hands" },
|
||
{ name = "腰带", invType = "INVTYPE_WAIST", items = {}, icon = "Interface\\PaperDoll\\UI-PaperDoll-Slot-Waist" },
|
||
{ name = "腿", invType = "INVTYPE_LEGS", items = {}, icon = "Interface\\PaperDoll\\UI-PaperDoll-Slot-Legs" },
|
||
{ name = "脚", invType = "INVTYPE_FEET", items = {}, icon = "Interface\\PaperDoll\\UI-PaperDoll-Slot-Feet" },
|
||
|
||
|
||
{ name = "主手", invType = "INVTYPE_WEAPONMAINHAND", items = {}, icon = "Interface\\PaperDoll\\UI-PaperDoll-Slot-MainHand" },
|
||
{ name = "副手", invType = "INVTYPE_WEAPONOFFHAND", items = {}, icon = "Interface\\PaperDoll\\UI-PaperDoll-Slot-Relic" },
|
||
{ name = "远程", invType = "INVTYPE_RANGED", items = {}, icon = "Interface\\PaperDoll\\UI-PaperDoll-Slot-Ranged" },
|
||
{ name = "颈部", invType = "INVTYPE_NECK", items = {}, icon = "Interface\\PaperDoll\\UI-PaperDoll-Slot-Neck" },
|
||
{ name = "戒指", invType = "INVTYPE_FINGER", items = {}, icon = "Interface\\PaperDoll\\UI-PaperDoll-Slot-Finger" },
|
||
{ name = "饰品", invType = "INVTYPE_TRINKET", items = {}, icon = "Interface\\PaperDoll\\UI-PaperDoll-Slot-Trinket" },
|
||
|
||
}
|
||
self.ALL_SLOTS = MODEL_SLOTS
|
||
-- 动态生成类型映射表,保证和槽位定义一致
|
||
self.typeToInvType = {}
|
||
for _, slot in ipairs(self.ALL_SLOTS) do
|
||
self.typeToInvType[slot.name] = slot.invType
|
||
end
|
||
end
|
||
|
||
-- 隐藏所有按钮
|
||
function SM_ItemCollectionUI:HideButtons()
|
||
for _, button in ipairs(self.buttons) do
|
||
button:Hide()
|
||
end
|
||
|
||
-- 如果有预览框也隐藏
|
||
if self.previewFrame and self.previewFrame:IsShown() then
|
||
self.previewFrame:Hide()
|
||
end
|
||
end
|
||
|
||
-- 显示所有按钮
|
||
function SM_ItemCollectionUI:ShowButtons()
|
||
for _, button in ipairs(self.buttons) do
|
||
button:Show()
|
||
|
||
-- 默认隐藏所有按钮的选中状态
|
||
if button.SelectedTexture then
|
||
button.SelectedTexture:Hide()
|
||
end
|
||
end
|
||
|
||
-- 恢复之前选中按钮的状态
|
||
if self.currentSelectedButton and self.currentSelectedButton.SelectedTexture then
|
||
self.currentSelectedButton.SelectedTexture:Show()
|
||
end
|
||
end
|
||
|
||
-- 清除所有模型选中状态
|
||
function SM_ItemCollectionUI:ClearModelSelection()
|
||
if self.selectedModel and self.selectedModel.TransmogStateTexture then
|
||
self.selectedModel.TransmogStateTexture:Hide()
|
||
end
|
||
self.selectedModel = nil
|
||
end
|
||
|
||
-- 设置模型选中状态
|
||
function SM_ItemCollectionUI:SelectModel(model)
|
||
-- 清除之前的选中状态
|
||
self:ClearModelSelection()
|
||
|
||
-- 设置当前模型为选中状态
|
||
if model then
|
||
if model.TransmogStateTexture then
|
||
model.TransmogStateTexture:Show()
|
||
|
||
-- 根据物品是否已获得设置选中纹理颜色
|
||
if model.itemData and model.itemData.obtained then
|
||
model.TransmogStateTexture:SetVertexColor(0, 1, 0, 0.7) -- 绿色选中纹理
|
||
else
|
||
model.TransmogStateTexture:SetVertexColor(1, 0, 0, 0.7) -- 红色选中纹理
|
||
end
|
||
end
|
||
self.selectedModel = model
|
||
end
|
||
end
|
||
|
||
-- 辅助函数:设置模型类型
|
||
function SM_ItemCollectionUI:SetModelType(model, type)
|
||
model.type = type
|
||
model:SetPosition(0, 0, 0)
|
||
model:SetFacing(0)
|
||
model:SetRotation(0)
|
||
|
||
if type == "player" then
|
||
model:SetUnit("player")
|
||
model.animID = ANIMATION_ARMOR_PREVIEW
|
||
elseif type == "main" then
|
||
model:SetCreature(2334) --隐身模型
|
||
model.animID = ANIMATION_WEAPON_PREVIEW_MAIN
|
||
elseif type == "off" then
|
||
model:SetCreature(2334)--隐身模型
|
||
model.animID = ANIMATION_WEAPON_PREVIEW_OFF
|
||
elseif type == "ranged" then
|
||
model:SetUnit("player")
|
||
model.animID = ANIMATION_RANGED_PREVIEW
|
||
end
|
||
end
|
||
|
||
-- 辅助函数:应用摄像机参数
|
||
function SM_ItemCollectionUI:ApplyCamera(model, cameraID)
|
||
-- 确保cameraID是有效的数值ID
|
||
if type(cameraID) == "string" then
|
||
return
|
||
end
|
||
|
||
local params = SM_CollectionData.Cameras[cameraID]
|
||
|
||
if params then
|
||
if #params == 4 then
|
||
-- 装备部位使用的格式:scale, leftRight, upDown, facing
|
||
local scale, leftRight, upDown, facing = unpack(params)
|
||
model:SetModelScale(scale)
|
||
model:SetPosition(0, leftRight, upDown) -- 装备使用相对偏移
|
||
model:SetFacing(facing or 0)
|
||
else
|
||
-- 武器使用的格式:scale, x, y, z, facing
|
||
local scale, x, y, z, facing = unpack(params)
|
||
model:SetModelScale(scale)
|
||
model:SetPosition(x, y, z) -- 武器使用绝对坐标
|
||
model:SetFacing(facing or 0)
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 辅助函数:冻结动画
|
||
function SM_ItemCollectionUI:FreezeAnimation(model)
|
||
-- 清除现有OnUpdate脚本
|
||
model:SetScript("OnUpdate", nil)
|
||
|
||
-- 设置正确的动画ID
|
||
local animID = model.animID or ANIMATION_ARMOR_PREVIEW
|
||
|
||
-- 设置动画序列
|
||
model:SetSequence(animID)
|
||
|
||
if animID ~= ANIMATION_RANGED_PREVIEW then
|
||
-- 其他动画:冻结在第一帧
|
||
model:SetSequenceTime(animID, 0)
|
||
-- 添加OnUpdate冻结 - 每帧重置动画时间
|
||
model:SetScript("OnUpdate", function(self)
|
||
self:SetSequenceTime(self.animID, 0)
|
||
end)
|
||
end
|
||
end
|
||
|
||
-- 辅助函数:更新属性加成
|
||
function SM_ItemCollectionUI:UpdateAttributes(itemID, itemType)
|
||
if not SM_Collections.MainFrame or not SM_Collections.MainFrame.RightSidePanel then
|
||
return
|
||
end
|
||
|
||
local rightSidePanel = SM_Collections.MainFrame.RightSidePanel
|
||
|
||
-- 检查物品是否已获得
|
||
local itemData = nil
|
||
if SM_CollectionsDB and SM_CollectionsDB.itemCache and SM_CollectionsDB.itemCache.items then
|
||
for _, item in ipairs(SM_CollectionsDB.itemCache.items) do
|
||
if tonumber(item.id) == tonumber(itemID) then
|
||
itemData = item
|
||
break
|
||
end
|
||
end
|
||
end
|
||
local isObtained = itemData and itemData.obtained
|
||
|
||
-- 清理其他收藏界面的属性按钮
|
||
if rightSidePanel.AttributeBonusFrame then
|
||
local children = { rightSidePanel.AttributeBonusFrame:GetChildren() }
|
||
for _, child in ipairs(children) do
|
||
if child:GetName() and string.find(child:GetName(), "SM_CollectionsAttributeutton") then
|
||
child:Hide()
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 确保属性加成框架存在并显示
|
||
if not rightSidePanel.AttributeBonusFrame then
|
||
-- 创建属性加成框架
|
||
local attributeFrame = CreateFrame("Frame", nil, rightSidePanel)
|
||
attributeFrame:SetSize(180, 30)
|
||
attributeFrame:SetPoint("TOP", rightSidePanel, "TOP", 0, -140)
|
||
|
||
local attributeTitle = attributeFrame:CreateFontString(nil, "OVERLAY")
|
||
attributeTitle:SetFont("Fonts\\ZYKai_T.ttf", 14, "OUTLINE")
|
||
attributeTitle:SetPoint("TOP", 0, 0)
|
||
attributeTitle:SetText("属性加成")
|
||
attributeTitle:SetTextColor(1, 0.82, 0)
|
||
|
||
rightSidePanel.AttributeBonusFrame = attributeFrame
|
||
end
|
||
|
||
-- 显示属性加成区域
|
||
rightSidePanel.AttributeBonusFrame:Show()
|
||
|
||
-- 清理旧的属性按钮和文本
|
||
if rightSidePanel.attributeButtons then
|
||
for _, button in ipairs(rightSidePanel.attributeButtons) do
|
||
button:Hide()
|
||
end
|
||
end
|
||
|
||
-- 清理旧的属性文本
|
||
if rightSidePanel.attributeTexts then
|
||
for _, text in ipairs(rightSidePanel.attributeTexts) do
|
||
text:Hide()
|
||
end
|
||
end
|
||
|
||
-- 重置数组
|
||
rightSidePanel.attributeButtons = {}
|
||
rightSidePanel.attributeTexts = {}
|
||
|
||
-- 创建属性容器,用于RefreshCollectionStatus函数统一更新颜色
|
||
if not rightSidePanel.attributesContainer then
|
||
rightSidePanel.attributesContainer = CreateFrame("Frame", nil, rightSidePanel.AttributeBonusFrame)
|
||
rightSidePanel.attributesContainer:SetSize(180, 200)
|
||
rightSidePanel.attributesContainer:SetPoint("TOP", rightSidePanel.AttributeBonusFrame, "TOP", 0, -30)
|
||
end
|
||
rightSidePanel.attributesContainer:Show()
|
||
|
||
-- 模拟不同物品的不同属性加成
|
||
local attributes = {}
|
||
|
||
-- 根据物品ID的不同添加不同的属性(示例)
|
||
if itemID % 2 == 0 then
|
||
table.insert(attributes, { name = "火焰伤害", value = "+500", isPositive = true })
|
||
else
|
||
table.insert(attributes, { name = "敏捷", value = "+20", isPositive = true })
|
||
end
|
||
|
||
if itemID % 3 == 0 then
|
||
table.insert(attributes, { name = "法术强度", value = "+200", isPositive = true })
|
||
end
|
||
|
||
if itemID % 5 == 0 then
|
||
table.insert(attributes, { name = "冰霜抗性", value = "+75", isPositive = true })
|
||
end
|
||
|
||
-- 根据物品类型添加特有的属性
|
||
if itemType == "INVTYPE_HEAD" or itemType == "INVTYPE_CHEST" or itemType == "INVTYPE_LEGS" then
|
||
table.insert(attributes, { name = "护甲", value = "+100", isPositive = true })
|
||
elseif itemType == "INVTYPE_WEAPONMAINHAND" then
|
||
table.insert(attributes, { name = "攻击强度", value = "+50", isPositive = true })
|
||
elseif itemType == "INVTYPE_TRINKET" then
|
||
table.insert(attributes, { name = "暴击率", value = "+2%", isPositive = true })
|
||
end
|
||
|
||
-- 添加属性按钮,与其他收藏页面风格一致
|
||
local buttonH = 150
|
||
local buttonW = 20
|
||
|
||
for i, attribute in ipairs(attributes) do
|
||
-- 创建带背景纹理的按钮
|
||
local button = CreateFrame("Button", "SM_ItemCollectionAttributeButton" .. i, rightSidePanel.attributesContainer)
|
||
button:SetSize(buttonH, buttonW)
|
||
button:SetNormalTexture("Interface\\AddOns\\SM_CollectionSystem\\Textures\\AttributeuttonTexture")
|
||
button:SetPoint("TOPLEFT", 0, -(i - 1) * buttonW)
|
||
|
||
-- 属性名称文本
|
||
local nameText = button:CreateFontString(nil, "OVERLAY")
|
||
nameText:SetPoint("LEFT", 10, 0)
|
||
nameText:SetFont("Fonts\\ZYKai_T.ttf", 10, "MONOCHROME")
|
||
nameText:SetText(attribute.name)
|
||
|
||
-- 根据物品是否已获得设置文本颜色
|
||
if isObtained then
|
||
nameText:SetTextColor(1, 1, 1) -- 白色
|
||
else
|
||
nameText:SetTextColor(0.5, 0.5, 0.5) -- 灰色
|
||
end
|
||
|
||
-- 属性数值文本
|
||
local valueText = button:CreateFontString(nil, "OVERLAY")
|
||
valueText:SetPoint("RIGHT", -5, 0)
|
||
valueText:SetFont("Fonts\\ZYKai_T.ttf", 10, "MONOCHROME")
|
||
valueText:SetText(attribute.value)
|
||
|
||
-- 根据物品是否已获得设置文本颜色
|
||
if isObtained then
|
||
valueText:SetTextColor(0, 1, 0) -- 绿色
|
||
else
|
||
valueText:SetTextColor(0.5, 0.5, 0.5) -- 灰色
|
||
end
|
||
|
||
button:Show()
|
||
|
||
-- 存储按钮引用
|
||
table.insert(rightSidePanel.attributeButtons, button)
|
||
|
||
-- 也将文本添加到文本数组中以便清理
|
||
table.insert(rightSidePanel.attributeTexts, nameText)
|
||
table.insert(rightSidePanel.attributeTexts, valueText)
|
||
end
|
||
end
|
||
|
||
-- 处理按钮点击事件
|
||
function SM_ItemCollectionUI:HandleButtonClick(slot)
|
||
if not self.currentPanel then
|
||
return
|
||
end
|
||
|
||
-- 记录当前选中的按钮
|
||
for _, button in ipairs(self.buttons) do
|
||
if button.slotData == slot then
|
||
self.currentSelectedButton = button
|
||
break
|
||
end
|
||
end
|
||
self.currentPage = 1
|
||
|
||
-- 确保按获得状态对物品排序
|
||
self:SortSlotItems(slot)
|
||
|
||
-- 显示物品预览
|
||
self:ShowItemPreview(slot, self.currentPanel)
|
||
end
|
||
|
||
-- 强制清理所有物品模型
|
||
function SM_ItemCollectionUI:ForceCleanupModels(panel)
|
||
-- 清理预览框架
|
||
if panel and panel.previewFrame then
|
||
local children = { panel.previewFrame:GetChildren() }
|
||
for _, child in ipairs(children) do
|
||
-- 清理所有事件处理器
|
||
child:SetScript("OnEnter", nil)
|
||
child:SetScript("OnLeave", nil)
|
||
child:SetScript("OnMouseDown", nil)
|
||
child:SetScript("OnMouseUp", nil)
|
||
child:SetScript("OnMouseWheel", nil)
|
||
child:SetScript("OnUpdate", nil)
|
||
-- 清理所有纹理
|
||
if child.newTexture then child.newTexture:Hide() end
|
||
if child.TransmogStateTexture then child.TransmogStateTexture:Hide() end
|
||
if child.Border then child.Border:Hide() end
|
||
-- 隐藏并移除
|
||
child:Hide()
|
||
child:SetParent(nil)
|
||
child:ClearAllPoints()
|
||
end
|
||
end
|
||
|
||
-- 清理全局缓存
|
||
collectgarbage("collect")
|
||
end
|
||
|
||
-- 显示物品预览
|
||
function SM_ItemCollectionUI:ShowItemPreview(slot, panel)
|
||
-- 确保物品已排序
|
||
self:SortSlotItems(slot)
|
||
|
||
-- 清除当前选中的模型
|
||
self:ClearModelSelection()
|
||
|
||
if not panel then
|
||
panel = self.currentPanel
|
||
end
|
||
|
||
if not panel then
|
||
return
|
||
end
|
||
|
||
-- 清理旧的预览内容
|
||
if panel.previewFrame and panel.previewFrame:IsShown() then
|
||
local children = { panel.previewFrame:GetChildren() }
|
||
for _, child in ipairs(children) do
|
||
child:Hide()
|
||
child:SetParent(nil)
|
||
end
|
||
panel.previewFrame:Hide()
|
||
end
|
||
|
||
-- 创建预览框架
|
||
local previewFrame = CreateFrame("Frame", "ItemCollectionPreviewFrame", panel)
|
||
previewFrame:SetSize(580, 400)
|
||
previewFrame:SetPoint("LEFT", SM_Collections.MainFrame, "LEFT", 30, -20)
|
||
previewFrame:SetBackdrop({
|
||
bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
|
||
})
|
||
previewFrame:Show()
|
||
panel.previewFrame = previewFrame
|
||
self.previewFrame = previewFrame
|
||
|
||
-- 判断是否是图标类物品
|
||
local isIconOnly = (slot.invType == "INVTYPE_NECK" or slot.invType == "INVTYPE_FINGER" or slot.invType == "INVTYPE_TRINKET")
|
||
|
||
-- 检查槽位是否有物品
|
||
if #slot.items == 0 then
|
||
-- 如果没有物品,显示一个提示信息
|
||
local noItemsText = previewFrame:CreateFontString(nil, "OVERLAY")
|
||
noItemsText:SetFont("Fonts\\ZYKai_T.ttf", 16, "OUTLINE")
|
||
noItemsText:SetPoint("CENTER", previewFrame, "CENTER", 0, 0)
|
||
noItemsText:SetText("该分类下暂无物品数据")
|
||
noItemsText:SetTextColor(1, 0.82, 0)
|
||
noItemsText:Show()
|
||
|
||
-- 更新右侧信息面板
|
||
if SM_Collections.MainFrame and SM_Collections.MainFrame.RightSidePanel then
|
||
if SM_Collections.MainFrame.RightSidePanel.MountNama then
|
||
SM_Collections.MainFrame.RightSidePanel.MountNama:SetText("无物品")
|
||
end
|
||
|
||
if SM_Collections.MainFrame.RightSidePanel.introText then
|
||
SM_Collections.MainFrame.RightSidePanel.introText:SetText("类型: " .. slot.name .. "\n暂无物品数据")
|
||
end
|
||
|
||
-- 清空属性加成显示
|
||
if SM_Collections.MainFrame.RightSidePanel.AttributeBonusFrame then
|
||
SM_Collections.MainFrame.RightSidePanel.AttributeBonusFrame:Hide()
|
||
end
|
||
end
|
||
|
||
return
|
||
end
|
||
|
||
local startIdx = (self.currentPage - 1) * self.itemsPerPage + 1
|
||
local endIdx = math.min(startIdx + self.itemsPerPage - 1, #slot.items)
|
||
|
||
if isIconOnly then
|
||
local modelFrames = {}
|
||
for j = startIdx, endIdx do
|
||
local itemID = slot.items[j]
|
||
if not itemID then break end
|
||
local pageIndex = j - startIdx
|
||
local row = math.floor(pageIndex / 6)
|
||
local col = pageIndex % 6
|
||
local model = CreateFrame("Frame", nil, previewFrame, "SM_CollectionSystemWardrobeItemsModelTemplate")
|
||
model:SetSize(78, 104)
|
||
model:SetPoint("TOPLEFT", 24 + col * 92, -10 - row * 120)
|
||
if model.Model then model.Model:Hide() end
|
||
local icon = model:CreateTexture(nil, "ARTWORK")
|
||
icon:SetSize(50, 50)
|
||
icon:SetPoint("CENTER", 0, 10)
|
||
icon:SetTexture(GetItemIcon(itemID))
|
||
icon:SetTexCoord(0.07, 0.93, 0.07, 0.93)
|
||
|
||
-- 检查物品是否已获得,设置灰度效果
|
||
local itemData = nil
|
||
if SM_CollectionsDB and SM_CollectionsDB.itemCache and SM_CollectionsDB.itemCache.items then
|
||
for _, item in ipairs(SM_CollectionsDB.itemCache.items) do
|
||
if tonumber(item.id) == tonumber(itemID) then
|
||
itemData = item
|
||
break
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 如果物品未获得,设置灰度效果
|
||
if not (itemData and itemData.obtained) then
|
||
icon:SetDesaturated(true)
|
||
end
|
||
|
||
-- 设置边框颜色
|
||
if model.Border then
|
||
if itemData and itemData.obtained then
|
||
model.Border:SetVertexColor(0, 1, 0, 1) -- 绿色边框
|
||
else
|
||
model.Border:SetVertexColor(1, 0, 0, 1) -- 红色边框
|
||
end
|
||
end
|
||
|
||
-- 设置高光颜色
|
||
local highlightTextures = { model:GetRegions() }
|
||
for _, region in ipairs(highlightTextures) do
|
||
if region:GetDrawLayer() == "HIGHLIGHT" then
|
||
if itemData and itemData.obtained then
|
||
region:SetVertexColor(0, 1, 0, 0.7) -- 绿色高光
|
||
else
|
||
region:SetVertexColor(1, 0, 0, 0.7) -- 红色高光
|
||
end
|
||
end
|
||
end
|
||
|
||
model.itemData = itemData or { id = itemID, obtained = false } -- 保存物品数据以便后续使用
|
||
|
||
-- 添加"NEW"标记,如果这是新获得的物品
|
||
if itemData and itemData.obtained and SM_Collections.NewItems and SM_Collections.NewItems.item and SM_Collections.NewItems.item[tonumber(itemID)] then
|
||
-- 创建NEW图标,使用OVERLAY层的最高级别(7)确保显示在最顶层
|
||
if not model.newTexture then
|
||
local newTexture = model:CreateTexture(nil, "OVERLAY", nil, 7)
|
||
newTexture:SetSize(32, 28)
|
||
newTexture:SetPoint("TOPRIGHT", model, "TOPRIGHT", 10, 10)
|
||
newTexture:SetTexture("Interface\\AddOns\\SM_CollectionSystem\\Textures\\New_Icon")
|
||
-- 确保纹理在最顶层
|
||
newTexture:SetDrawLayer("OVERLAY", 7)
|
||
model.newTexture = newTexture
|
||
else
|
||
model.newTexture:Show()
|
||
-- 确保纹理在最顶层
|
||
model.newTexture:SetDrawLayer("OVERLAY", 7)
|
||
end
|
||
end
|
||
|
||
if model.TransmogStateTexture then model.TransmogStateTexture:Hide() end
|
||
table.insert(modelFrames, model)
|
||
model:Show()
|
||
model:EnableMouse(true)
|
||
model:SetScript("OnEnter", function(self)
|
||
-- 处理NEW图标
|
||
if self.newTexture and self.newTexture:IsShown() then
|
||
self.newTexture:Hide()
|
||
-- 从NewItems表中移除
|
||
if SM_Collections and SM_Collections.NewItems and SM_Collections.NewItems.item then
|
||
SM_Collections.NewItems.item[tonumber(itemID)] = nil
|
||
end
|
||
end
|
||
|
||
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
||
GameTooltip:SetHyperlink("item:" .. itemID)
|
||
GameTooltip:Show()
|
||
end)
|
||
model:SetScript("OnLeave", function() GameTooltip:Hide() end)
|
||
local currentItemID = itemID
|
||
local currentModel = model
|
||
model:SetScript("OnMouseDown", function(self)
|
||
SM_ItemCollectionUI:SelectModel(currentModel)
|
||
if SM_Collections.MainFrame and SM_Collections.MainFrame.RightSidePanel then
|
||
local itemName = GetItemInfo(currentItemID)
|
||
if SM_Collections.MainFrame.RightSidePanel.MountNama then
|
||
SM_Collections.MainFrame.RightSidePanel.MountNama:SetText(itemName or "")
|
||
end
|
||
if SM_Collections.MainFrame.RightSidePanel.introText then
|
||
SM_Collections.MainFrame.RightSidePanel.introText:SetText("物品ID: " ..
|
||
currentItemID .. "\n类型: " .. slot.name)
|
||
end
|
||
SM_ItemCollectionUI:UpdateAttributes(currentItemID, slot.invType)
|
||
end
|
||
end)
|
||
end
|
||
if #modelFrames > 0 and slot.items[startIdx] then
|
||
local firstModel = modelFrames[1]
|
||
self:SelectModel(firstModel)
|
||
local itemID = slot.items[startIdx]
|
||
local itemName = GetItemInfo(itemID)
|
||
|
||
|
||
|
||
if SM_Collections.MainFrame and SM_Collections.MainFrame.RightSidePanel then
|
||
if SM_Collections.MainFrame.RightSidePanel.MountNama then
|
||
SM_Collections.MainFrame.RightSidePanel.MountNama:SetText(itemName or "")
|
||
end
|
||
if SM_Collections.MainFrame.RightSidePanel.introText then
|
||
SM_Collections.MainFrame.RightSidePanel.introText:SetText("物品ID: " .. itemID .. "\n类型: " .. slot
|
||
.name)
|
||
end
|
||
self:UpdateAttributes(itemID, slot.invType)
|
||
end
|
||
end
|
||
else
|
||
local modelFrames = {}
|
||
for j = startIdx, endIdx do
|
||
local itemID = slot.items[j]
|
||
if not itemID then break end
|
||
local pageIndex = j - startIdx
|
||
local row = math.floor(pageIndex / 6)
|
||
local col = pageIndex % 6
|
||
local model = CreateFrame("DressUpModel", nil, previewFrame, "SM_CollectionSystemWardrobeItemsModelTemplate")
|
||
model:SetSize(78, 104)
|
||
model:SetPoint("TOPLEFT", 24 + col * 92, -10 - row * 120)
|
||
if model.TransmogStateTexture then model.TransmogStateTexture:Hide() end
|
||
|
||
-- 检查物品是否已获得,设置灰度效果
|
||
local itemData = nil
|
||
if SM_CollectionsDB and SM_CollectionsDB.itemCache and SM_CollectionsDB.itemCache.items then
|
||
for _, item in ipairs(SM_CollectionsDB.itemCache.items) do
|
||
if tonumber(item.id) == tonumber(itemID) then
|
||
itemData = item
|
||
break
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 设置边框颜色
|
||
if model.Border then
|
||
if itemData and itemData.obtained then
|
||
model.Border:SetVertexColor(0, 1, 0, 1) -- 绿色边框
|
||
else
|
||
model.Border:SetVertexColor(1, 0, 0, 1) -- 红色边框
|
||
end
|
||
end
|
||
|
||
-- 设置高光颜色
|
||
local highlightTextures = { model:GetRegions() }
|
||
for _, region in ipairs(highlightTextures) do
|
||
if region:GetDrawLayer() == "HIGHLIGHT" then
|
||
if itemData and itemData.obtained then
|
||
region:SetVertexColor(0, 1, 0, 0.7) -- 绿色高光
|
||
else
|
||
region:SetVertexColor(1, 0, 0, 0.7) -- 红色高光
|
||
end
|
||
end
|
||
end
|
||
|
||
model.itemData = itemData or { id = itemID, obtained = false } -- 保存物品数据以便后续使用
|
||
|
||
-- 添加"NEW"标记,如果这是新获得的物品
|
||
if itemData and itemData.obtained and SM_Collections.NewItems and SM_Collections.NewItems.item and SM_Collections.NewItems.item[tonumber(itemID)] then
|
||
-- 创建NEW图标,使用OVERLAY层的最高级别(7)确保显示在最顶层
|
||
if not model.newTexture then
|
||
local newTexture = model:CreateTexture(nil, "OVERLAY", nil, 7)
|
||
newTexture:SetSize(32, 28)
|
||
newTexture:SetPoint("TOPRIGHT", model, "TOPRIGHT", 10, 10)
|
||
newTexture:SetTexture("Interface\\AddOns\\SM_CollectionSystem\\Textures\\New_Icon")
|
||
-- 确保纹理在最顶层
|
||
newTexture:SetDrawLayer("OVERLAY", 7)
|
||
model.newTexture = newTexture
|
||
else
|
||
model.newTexture:Show()
|
||
-- 确保纹理在最顶层
|
||
model.newTexture:SetDrawLayer("OVERLAY", 7)
|
||
end
|
||
end
|
||
|
||
table.insert(modelFrames, model)
|
||
model:Show()
|
||
model:EnableMouse(true)
|
||
model:SetScript("OnEnter", function(self)
|
||
-- 处理NEW图标
|
||
if self.newTexture and self.newTexture:IsShown() then
|
||
self.newTexture:Hide()
|
||
-- 从NewItems表中移除
|
||
if SM_Collections and SM_Collections.NewItems and SM_Collections.NewItems.item then
|
||
SM_Collections.NewItems.item[tonumber(itemID)] = nil
|
||
end
|
||
end
|
||
|
||
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
||
GameTooltip:SetHyperlink("item:" .. itemID)
|
||
GameTooltip:Show()
|
||
end)
|
||
model:SetScript("OnLeave", function(self) GameTooltip:Hide() end)
|
||
local currentItemID = itemID
|
||
local currentModel = model
|
||
model:SetScript("OnMouseDown", function(self)
|
||
SM_ItemCollectionUI:SelectModel(currentModel)
|
||
if SM_Collections.MainFrame and SM_Collections.MainFrame.RightSidePanel then
|
||
local itemName = GetItemInfo(currentItemID)
|
||
if SM_Collections.MainFrame.RightSidePanel.MountNama then
|
||
SM_Collections.MainFrame.RightSidePanel.MountNama:SetText(itemName or "")
|
||
end
|
||
if SM_Collections.MainFrame.RightSidePanel.introText then
|
||
SM_Collections.MainFrame.RightSidePanel.introText:SetText("物品ID: " ..
|
||
currentItemID .. "\n类型: " .. slot.name)
|
||
-- 获取物品的 obtained 状态
|
||
local itemData = nil
|
||
for _, item in ipairs(SM_CollectionsDB.itemCache and SM_CollectionsDB.itemCache.items or {}) do
|
||
if tonumber(item.id) == tonumber(currentItemID) then
|
||
itemData = item
|
||
break
|
||
end
|
||
end
|
||
|
||
-- 添加状态文本
|
||
if not SM_Collections.MainFrame.RightSidePanel.statusText then
|
||
SM_Collections.MainFrame.RightSidePanel.statusText = SM_Collections.MainFrame.RightSidePanel
|
||
:CreateFontString(nil, "OVERLAY")
|
||
SM_Collections.MainFrame.RightSidePanel.statusText:SetFont("Fonts\\ZYKai_T.ttf", 14,
|
||
"OUTLINE")
|
||
SM_Collections.MainFrame.RightSidePanel.statusText:SetPoint("TOP",
|
||
SM_Collections.MainFrame.RightSidePanel.introText, "BOTTOM", 0, -10)
|
||
end
|
||
local statusText = itemData and itemData.obtained and "|cFF00FF00已获得|r" or "|cFFFF0000未获得|r"
|
||
SM_Collections.MainFrame.RightSidePanel.statusText:SetText(statusText)
|
||
SM_Collections.MainFrame.RightSidePanel.statusText:Show()
|
||
end
|
||
SM_ItemCollectionUI:UpdateAttributes(currentItemID, slot.invType)
|
||
end
|
||
end)
|
||
if slot.invType == "INVTYPE_WEAPONMAINHAND" or slot.invType == "INVTYPE_WEAPONOFFHAND" then
|
||
model:ClearModel()
|
||
if slot.invType == "INVTYPE_WEAPONOFFHAND" then
|
||
model.originalType = "off"
|
||
self:SetModelType(model, "off")
|
||
else
|
||
model.originalType = "main"
|
||
self:SetModelType(model, "main")
|
||
end
|
||
model:Undress()
|
||
local success, error = pcall(function() model:TryOn(itemID) end)
|
||
local weaponCameraID
|
||
if slot.invType == "INVTYPE_WEAPONOFFHAND" then
|
||
weaponCameraID = SM_CollectionData:GetWeaponCameraID("INVTYPE_WEAPONOFFHAND")
|
||
else
|
||
weaponCameraID = SM_CollectionData:GetWeaponCameraID("INVTYPE_WEAPONMAINHAND")
|
||
end
|
||
self:ApplyCamera(model, weaponCameraID)
|
||
elseif slot.invType == "INVTYPE_RANGED" then
|
||
model:ClearModel()
|
||
model:SetUnit("player")
|
||
model.animID = ANIMATION_RANGED_PREVIEW
|
||
model:Undress()
|
||
local success, error = pcall(function() model:TryOn(itemID) end)
|
||
local cameraID = SM_CollectionData:GetCharacterCameraID(slot.invType)
|
||
self:ApplyCamera(model, cameraID)
|
||
model:EnableMouse(true)
|
||
model:EnableMouseWheel(true)
|
||
model.isRotating = false
|
||
model.lastX = 0
|
||
local currentModel = model
|
||
local currentItemID = itemID
|
||
local updateFrame = CreateFrame("Frame", nil, model)
|
||
updateFrame:SetScript("OnUpdate", function(self, elapsed)
|
||
if currentModel.isRotating then
|
||
local x = GetCursorPosition()
|
||
local delta = (x - (currentModel.lastX or x)) * 0.01
|
||
currentModel.lastX = x
|
||
currentModel:SetFacing(currentModel:GetFacing() + delta)
|
||
end
|
||
end)
|
||
model:SetScript("OnMouseDown", function(self, button)
|
||
if button == "LeftButton" then
|
||
SM_ItemCollectionUI:SelectModel(currentModel)
|
||
if SM_Collections.MainFrame and SM_Collections.MainFrame.RightSidePanel then
|
||
local itemName = GetItemInfo(currentItemID)
|
||
if SM_Collections.MainFrame.RightSidePanel.MountNama then
|
||
SM_Collections.MainFrame.RightSidePanel.MountNama:SetText(itemName or "")
|
||
end
|
||
if SM_Collections.MainFrame.RightSidePanel.introText then
|
||
SM_Collections.MainFrame.RightSidePanel.introText:SetText("物品ID: " ..
|
||
currentItemID .. "\n类型: " .. slot.name)
|
||
end
|
||
SM_ItemCollectionUI:UpdateAttributes(currentItemID, slot.invType)
|
||
end
|
||
self.isRotating = true
|
||
self.lastX = GetCursorPosition()
|
||
end
|
||
end)
|
||
model:SetScript("OnMouseWheel", function(self, delta)
|
||
local rotationAmount = math.rad(15)
|
||
self:SetFacing(self:GetFacing() - (delta * rotationAmount))
|
||
end)
|
||
model:SetScript("OnMouseUp", function(self, button)
|
||
if button == "LeftButton" then
|
||
self.isRotating = false
|
||
end
|
||
end)
|
||
model:SetScript("OnLeave", function(self)
|
||
if self.isRotating then
|
||
self.isRotating = false
|
||
end
|
||
GameTooltip:Hide()
|
||
end)
|
||
else
|
||
self:SetModelType(model, "player")
|
||
local success, error = pcall(function() model:TryOn(itemID) end)
|
||
local cameraID = SM_CollectionData:GetCharacterCameraID(slot.invType)
|
||
self:ApplyCamera(model, cameraID)
|
||
end
|
||
self:FreezeAnimation(model)
|
||
if model.NewString and model.NewGlow then end
|
||
if model.Favorite and model.Favorite.Icon then end
|
||
if model.HideVisual and model.HideVisual.Icon then end
|
||
end
|
||
if #modelFrames > 0 and slot.items[startIdx] then
|
||
local firstModel = modelFrames[1]
|
||
self:SelectModel(firstModel)
|
||
local itemID = slot.items[startIdx]
|
||
local itemName = GetItemInfo(itemID)
|
||
if SM_Collections.MainFrame and SM_Collections.MainFrame.RightSidePanel then
|
||
if SM_Collections.MainFrame.RightSidePanel.MountNama then
|
||
SM_Collections.MainFrame.RightSidePanel.MountNama:SetText(itemName or "")
|
||
end
|
||
if SM_Collections.MainFrame.RightSidePanel.introText then
|
||
SM_Collections.MainFrame.RightSidePanel.introText:SetText("物品ID: " .. itemID .. "\n类型: " .. slot
|
||
.name)
|
||
end
|
||
self:UpdateAttributes(itemID, slot.invType)
|
||
end
|
||
end
|
||
end
|
||
self:CreatePageButtons(panel, slot)
|
||
|
||
-- 在切换部位时更新物品状态显示
|
||
if #slot.items > 0 then
|
||
local startIdx = (self.currentPage - 1) * self.itemsPerPage + 1
|
||
local itemID = slot.items[startIdx]
|
||
if itemID then
|
||
-- 获取物品的 obtained 状态
|
||
local itemData = nil
|
||
if SM_CollectionsDB and SM_CollectionsDB.itemCache and SM_CollectionsDB.itemCache.items then
|
||
for _, item in ipairs(SM_CollectionsDB.itemCache.items) do
|
||
if tonumber(item.id) == tonumber(itemID) then
|
||
itemData = item
|
||
break
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 添加或更新状态文本
|
||
if SM_Collections.MainFrame and SM_Collections.MainFrame.RightSidePanel then
|
||
if not SM_Collections.MainFrame.RightSidePanel.statusText then
|
||
SM_Collections.MainFrame.RightSidePanel.statusText = SM_Collections.MainFrame.RightSidePanel
|
||
:CreateFontString(nil, "OVERLAY")
|
||
SM_Collections.MainFrame.RightSidePanel.statusText:SetFont("Fonts\\ZYKai_T.ttf", 14, "OUTLINE")
|
||
SM_Collections.MainFrame.RightSidePanel.statusText:SetPoint("TOP",
|
||
SM_Collections.MainFrame.RightSidePanel.introText, "BOTTOM", 0, -10)
|
||
end
|
||
local statusText = itemData and itemData.obtained and "|cFF00FF00已获得|r" or "|cFFFF0000未获得|r"
|
||
SM_Collections.MainFrame.RightSidePanel.statusText:SetText(statusText)
|
||
SM_Collections.MainFrame.RightSidePanel.statusText:Show()
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 创建分页按钮
|
||
function SM_ItemCollectionUI:CreatePageButtons(panel, slot)
|
||
-- 移除旧按钮
|
||
if self.pageButtons.prev then self.pageButtons.prev:Hide() end
|
||
if self.pageButtons.next then self.pageButtons.next:Hide() end
|
||
if self.pageButtons.text then self.pageButtons.text:Hide() end
|
||
|
||
-- 计算总页数
|
||
local totalItems = #slot.items
|
||
self.totalPages = math.max(1, math.ceil(totalItems / self.itemsPerPage))
|
||
if self.currentPage > self.totalPages then self.currentPage = self.totalPages end
|
||
|
||
-- 上一页按钮
|
||
local prevBtn = CreateFrame("Button", nil, panel, "UIPanelButtonTemplate")
|
||
prevBtn:SetSize(60, 24)
|
||
prevBtn:SetPoint("BOTTOM", panel, "BOTTOM", 0, 35)
|
||
prevBtn:SetText("上一页")
|
||
prevBtn:SetScript("OnClick", function()
|
||
if self.currentPage > 1 then
|
||
self.currentPage = self.currentPage - 1
|
||
-- 确保物品始终保持排序
|
||
self:SortSlotItems(slot)
|
||
-- 强制清理旧的预览内容
|
||
if panel.previewFrame then
|
||
panel.previewFrame:Hide()
|
||
panel.previewFrame:SetParent(nil)
|
||
panel.previewFrame = nil
|
||
end
|
||
self:ShowItemPreview(slot, panel)
|
||
end
|
||
end)
|
||
if self.currentPage <= 1 then
|
||
prevBtn:Disable()
|
||
else
|
||
prevBtn:Enable()
|
||
end
|
||
prevBtn:Show()
|
||
self.pageButtons.prev = prevBtn
|
||
|
||
-- 下一页按钮
|
||
local nextBtn = CreateFrame("Button", nil, panel, "UIPanelButtonTemplate")
|
||
nextBtn:SetSize(60, 24)
|
||
nextBtn:SetPoint("BOTTOM", panel, "BOTTOM", 160, 35)
|
||
nextBtn:SetText("下一页")
|
||
nextBtn:SetScript("OnClick", function()
|
||
if self.currentPage < self.totalPages then
|
||
self.currentPage = self.currentPage + 1
|
||
-- 确保物品始终保持排序
|
||
self:SortSlotItems(slot)
|
||
-- 强制清理旧的预览内容
|
||
if panel.previewFrame then
|
||
panel.previewFrame:Hide()
|
||
panel.previewFrame:SetParent(nil)
|
||
panel.previewFrame = nil
|
||
end
|
||
self:ShowItemPreview(slot, panel)
|
||
end
|
||
end)
|
||
if self.currentPage >= self.totalPages then
|
||
nextBtn:Disable()
|
||
else
|
||
nextBtn:Enable()
|
||
end
|
||
nextBtn:Show()
|
||
self.pageButtons.next = nextBtn
|
||
|
||
-- 页码文本
|
||
local pageText = panel:CreateFontString(nil, "OVERLAY", "GameFontNormal")
|
||
pageText:SetPoint("BOTTOM", panel, "BOTTOM", 80, 40)
|
||
pageText:SetText(string.format("第 %d / %d 页", self.currentPage, self.totalPages))
|
||
pageText:SetDrawLayer("OVERLAY", 7) -- 使用子层级7,确保在OVERLAY层的最顶部
|
||
pageText:Show()
|
||
self.pageButtons.text = pageText
|
||
end
|
||
|
||
-- 新增函数:对槽位中的物品按获得状态排序
|
||
function SM_ItemCollectionUI:SortSlotItems(slot)
|
||
if not slot or not slot.items or #slot.items == 0 then
|
||
return
|
||
end
|
||
|
||
-- 对物品按照已获得状态进行排序,已获得的排在前面
|
||
local sortedItems = {}
|
||
|
||
-- 首先创建一个带状态的物品列表
|
||
for _, itemID in ipairs(slot.items) do
|
||
local isObtained = false
|
||
if SM_CollectionsDB and SM_CollectionsDB.itemCache and SM_CollectionsDB.itemCache.items then
|
||
for _, item in ipairs(SM_CollectionsDB.itemCache.items) do
|
||
if tonumber(item.id) == tonumber(itemID) then
|
||
isObtained = item.obtained
|
||
break
|
||
end
|
||
end
|
||
end
|
||
table.insert(sortedItems, { id = itemID, obtained = isObtained })
|
||
end
|
||
|
||
-- 按照获得状态进行排序
|
||
table.sort(sortedItems, function(a, b)
|
||
if a.obtained and not b.obtained then
|
||
return true -- a排在b前面
|
||
elseif not a.obtained and b.obtained then
|
||
return false -- b排在a前面
|
||
else
|
||
-- 如果获得状态相同,按ID排序
|
||
return a.id < b.id
|
||
end
|
||
end)
|
||
|
||
-- 打印排序前后的状态
|
||
local beforeIDs = {}
|
||
for i, id in ipairs(slot.items) do
|
||
beforeIDs[i] = id
|
||
end
|
||
|
||
local afterIDs = {}
|
||
for i, item in ipairs(sortedItems) do
|
||
afterIDs[i] = item.id
|
||
end
|
||
|
||
-- 更新排序后的物品ID列表
|
||
local newItems = {}
|
||
for _, item in ipairs(sortedItems) do
|
||
table.insert(newItems, item.id)
|
||
end
|
||
slot.items = newItems
|
||
return true -- 返回true表示排序成功
|
||
end
|
||
|
||
-- 新增函数:更新物品获得状态并重新排序显示
|
||
function SM_ItemCollectionUI:UpdateItemObtainedStatus(itemID, isObtained)
|
||
if not itemID then return end
|
||
|
||
-- 更新物品缓存中的状态
|
||
local itemUpdated = false
|
||
if SM_CollectionsDB and SM_CollectionsDB.itemCache and SM_CollectionsDB.itemCache.items then
|
||
for _, item in ipairs(SM_CollectionsDB.itemCache.items) do
|
||
if tonumber(item.id) == tonumber(itemID) then
|
||
item.obtained = isObtained
|
||
itemUpdated = true
|
||
break
|
||
end
|
||
end
|
||
end
|
||
|
||
if not itemUpdated then
|
||
return false
|
||
end
|
||
|
||
-- 如果物品是新获得的,添加到NewItems表中
|
||
if isObtained then
|
||
if not SM_Collections.NewItems then
|
||
SM_Collections.NewItems = {}
|
||
end
|
||
if not SM_Collections.NewItems.item then
|
||
SM_Collections.NewItems.item = {}
|
||
end
|
||
SM_Collections.NewItems.item[tonumber(itemID)] = true
|
||
end
|
||
|
||
-- 找到当前物品所在的槽位
|
||
local currentSlot = nil
|
||
for _, slot in ipairs(self.ALL_SLOTS) do
|
||
for _, slotItemID in ipairs(slot.items) do
|
||
if tonumber(slotItemID) == tonumber(itemID) then
|
||
currentSlot = slot
|
||
break
|
||
end
|
||
end
|
||
if currentSlot then break end
|
||
end
|
||
|
||
if not currentSlot then
|
||
print("[更新] 警告:物品", itemID, "未在任何槽位中找到")
|
||
return false
|
||
end
|
||
|
||
-- 重新排序当前槽位的物品
|
||
self:SortSlotItems(currentSlot)
|
||
|
||
-- 如果当前正在显示该槽位,则刷新显示
|
||
if self.currentPanel and self.currentSelectedButton and self.currentSelectedButton.slotData == currentSlot then
|
||
self:ShowItemPreview(currentSlot, self.currentPanel)
|
||
end
|
||
|
||
return true
|
||
end
|
||
|
||
-- 清除所有按钮
|
||
function SM_ItemCollectionUI:ClearButtons()
|
||
for _, button in ipairs(self.buttons) do
|
||
button:Hide()
|
||
button:SetParent(nil)
|
||
end
|
||
self.buttons = {}
|
||
end
|
||
|
||
-- 创建按钮
|
||
function SM_ItemCollectionUI:CreateButtons()
|
||
-- 先清除之前的按钮
|
||
self:ClearButtons()
|
||
|
||
local lastButton = nil -- 记录最后一个按钮(包括正常和特殊按钮)
|
||
local specialButtonsOffset = false
|
||
|
||
-- 创建所有槽位按钮
|
||
for i, slot in ipairs(self.ALL_SLOTS) do
|
||
local btn
|
||
local slotName = string.lower(string.gsub(slot.invType, "INVTYPE_", ""))
|
||
|
||
-- 对于没有对应纹理的槽位(颈部、戒指、饰品),创建独立按钮
|
||
if slotName == "neck" or slotName == "finger" or slotName == "trinket" then
|
||
-- 创建独立按钮,不使用模板
|
||
btn = CreateFrame("Button", nil, SM_ItemCollectionUI.currentPanel)
|
||
btn:SetSize(30, 30)
|
||
-- 智能定位:相对于最后一个按钮
|
||
if lastButton then
|
||
local xOffset = not specialButtonsOffset and 0 or 5 -- 第一个用10,后续用8
|
||
local yOffset = not specialButtonsOffset and 2 or 0 -- 只有第一个向上偏移
|
||
if not specialButtonsOffset then specialButtonsOffset = true end
|
||
|
||
btn:SetPoint("LEFT", lastButton, "RIGHT", xOffset, yOffset)
|
||
else
|
||
btn:SetPoint("TOPLEFT", 90, -43)
|
||
end
|
||
-- 添加正常纹理
|
||
local normalTexture = btn:CreateTexture(nil, "BACKGROUND")
|
||
normalTexture:SetSize(28, 28)
|
||
normalTexture:SetPoint("CENTER")
|
||
normalTexture:SetTexture(slot.icon) -- ICON_SLOTS 图标纹理
|
||
SetPortraitToTexture(normalTexture, slot.icon) -- 圆形肖像
|
||
btn.NormalTexture = normalTexture
|
||
|
||
-- 添加高光纹理(使用通用的高光效果)
|
||
local highlightTexture = btn:CreateTexture(nil, "HIGHLIGHT")
|
||
highlightTexture:SetSize(30, 30)
|
||
highlightTexture:SetPoint("CENTER", 0, 0)
|
||
highlightTexture:SetTexture("Interface\\AddOns\\SM_CollectionSystem\\Interface\\ContainerFrame\\Bags")
|
||
highlightTexture:SetTexCoord(0.1640625, 0.3046875, 0.6875, 0.828125) -- 这是XML里的
|
||
highlightTexture:SetBlendMode("ADD")
|
||
|
||
-- 添加覆盖纹理
|
||
local ArtworkTexture = btn:CreateTexture(nil, "OVERLAY")
|
||
ArtworkTexture:SetSize(33, 33)
|
||
ArtworkTexture:SetPoint("CENTER")
|
||
ArtworkTexture:SetTexture("Interface\\AddOns\\SM_CollectionSystem\\Textures\\NeckButon_ARTWORK")
|
||
--SetPortraitToTexture(ArtworkTexture, "Interface\\AddOns\\SM_CollectionSystem\\Textures\\NeckButon_ARTWORK")
|
||
btn.ArtworkTexture = ArtworkTexture
|
||
|
||
-- local selectedTexture = btn:CreateTexture(nil, "OVERLAY", nil, 1)
|
||
-- selectedTexture:SetSize(45, 47)
|
||
-- selectedTexture:SetPoint("CENTER", 0, -2)
|
||
-- selectedTexture:SetTexture("Interface\\AddOns\\SM_CollectionSystem\\Interface\\Transmogrify\\Transmogrify")
|
||
-- selectedTexture:SetTexCoord(0.734375, 0.802734375, 0.171875, 0.244140625) -- 这是XML里的
|
||
-- selectedTexture:Hide()
|
||
-- btn.SelectedTexture = selectedTexture
|
||
else
|
||
btn = CreateFrame("Button", nil, SM_ItemCollectionUI.currentPanel, "SM_CollectionSystemWardrobeSlotButtonTemplate")
|
||
btn:SetSize(40, 40)
|
||
btn:SetPoint("TOPLEFT", 80 + (i - 1) * 35, 35)
|
||
|
||
-- 设置图标
|
||
if btn.NormalTexture then
|
||
-- 增加纹理大小以适配按钮
|
||
btn.NormalTexture:SetSize(40, 40)
|
||
|
||
-- 如果有高亮纹理,调整其大小
|
||
if btn.Highlight then
|
||
btn.Highlight:SetSize(28, 28)
|
||
btn.Highlight:SetPoint("CENTER", 0, 2)
|
||
end
|
||
|
||
-- 如果有选中纹理,调整其大小
|
||
if btn.SelectedTexture then
|
||
btn.SelectedTexture:SetSize(45, 48)
|
||
btn.SelectedTexture:SetPoint("CENTER")
|
||
end
|
||
|
||
-- 使用SetAtlasMixin设置图标
|
||
SM_Collections:Mixin(btn.NormalTexture, SetAtlasMixin)
|
||
|
||
-- 根据槽位类型映射到合适的atlas纹理名称
|
||
local atlasName = "transmog-nav-slot-"
|
||
|
||
-- 处理特殊槽位名称映射
|
||
if slotName == "head" then
|
||
atlasName = atlasName .. "head"
|
||
elseif slotName == "shoulder" then
|
||
atlasName = atlasName .. "shoulder"
|
||
elseif slotName == "body" then
|
||
atlasName = atlasName .. "shirt"
|
||
elseif slotName == "chest" then
|
||
atlasName = atlasName .. "chest"
|
||
elseif slotName == "waist" then
|
||
atlasName = atlasName .. "waist"
|
||
elseif slotName == "legs" then
|
||
atlasName = atlasName .. "legs"
|
||
elseif slotName == "feet" then
|
||
atlasName = atlasName .. "feet"
|
||
elseif slotName == "wrist" then
|
||
atlasName = atlasName .. "wrist"
|
||
elseif slotName == "hand" then
|
||
atlasName = atlasName .. "hands"
|
||
elseif slotName == "cloak" then
|
||
atlasName = atlasName .. "back"
|
||
elseif slotName == "weaponmainhand" then
|
||
atlasName = atlasName .. "mainhand"
|
||
elseif slotName == "weaponoffhand" then
|
||
atlasName = atlasName .. "secondaryhand"
|
||
elseif slotName == "ranged" then
|
||
atlasName = atlasName .. "ranged"
|
||
elseif slotName == "tabard" then
|
||
atlasName = atlasName .. "tabard"
|
||
end
|
||
|
||
-- 应用atlas纹理
|
||
if not string.find(atlasName, "transmog-nav-slot-$") then
|
||
btn.NormalTexture:SetAtlas(atlasName, true)
|
||
end
|
||
end
|
||
end
|
||
|
||
-- 更新最后一个按钮的引用(关键修改)
|
||
lastButton = btn
|
||
|
||
-- 设置事件处理
|
||
btn:SetScript("OnEnter", function(self)
|
||
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
|
||
GameTooltip:SetText(slot.name)
|
||
GameTooltip:Show()
|
||
|
||
-- 只有在按钮未被选中时才显示高光纹理
|
||
if self.Highlight and (not self.SelectedTexture or not self.SelectedTexture:IsShown()) then
|
||
self.Highlight:Show()
|
||
end
|
||
end)
|
||
|
||
btn:SetScript("OnLeave", function(self)
|
||
GameTooltip:Hide()
|
||
|
||
-- 隐藏高亮纹理
|
||
if self.Highlight then
|
||
self.Highlight:Hide()
|
||
end
|
||
end)
|
||
|
||
-- 关键改动:将slot对象存储在按钮上,而不是依赖闭包
|
||
btn.slotData = slot
|
||
btn:SetScript("OnClick", function(self)
|
||
-- 播放点击音效
|
||
PlaySound("igSpellBookSpellIconPickup")
|
||
|
||
-- 清除所有按钮的选中状态
|
||
for _, button in ipairs(SM_ItemCollectionUI.buttons) do
|
||
if button.SelectedTexture then
|
||
button.SelectedTexture:Hide()
|
||
end
|
||
end
|
||
|
||
-- 显示当前按钮的选中状态
|
||
if self.SelectedTexture then
|
||
self.SelectedTexture:Show()
|
||
end
|
||
|
||
-- 直接从按钮属性中获取slot数据
|
||
SM_ItemCollectionUI:HandleButtonClick(self.slotData)
|
||
end)
|
||
|
||
table.insert(self.buttons, btn)
|
||
end
|
||
|
||
-- 默认隐藏所有按钮
|
||
self:HideButtons()
|
||
end
|
||
|
||
-- 显示物品收藏界面
|
||
function SM_ItemCollectionUI:ShowItemCollectionUI(parent)
|
||
-- 确保已初始化(防止ALL_SLOTS未初始化导致缓存数据无法分类)
|
||
if not self.initialized then
|
||
self:Init()
|
||
end
|
||
|
||
-- 创建新的物品分栏面板
|
||
local panel = CreateFrame("Frame", "SM_CollectionsItemsPanel", parent)
|
||
panel:SetAllPoints()
|
||
self.currentPanel = panel
|
||
|
||
-- 隐藏右侧召唤按钮
|
||
if SM_Collections.MainFrame and SM_Collections.MainFrame.RightSidePanel and SM_Collections.MainFrame.RightSidePanel.CallButon then
|
||
SM_Collections.MainFrame.RightSidePanel.CallButon:Hide()
|
||
end
|
||
|
||
-- 确保属性加成框架存在并显示
|
||
if SM_Collections.MainFrame and SM_Collections.MainFrame.RightSidePanel then
|
||
if SM_Collections.MainFrame.RightSidePanel.attributeTexts then
|
||
for _, text in ipairs(SM_Collections.MainFrame.RightSidePanel.attributeTexts) do
|
||
text:Hide()
|
||
end
|
||
SM_Collections.MainFrame.RightSidePanel.attributeTexts = {}
|
||
end
|
||
if not SM_Collections.MainFrame.RightSidePanel.AttributeBonusFrame then
|
||
local attributeFrame = CreateFrame("Frame", nil, SM_Collections.MainFrame.RightSidePanel)
|
||
attributeFrame:SetSize(180, 30)
|
||
attributeFrame:SetPoint("TOP", SM_Collections.MainFrame.RightSidePanel, "TOP", 0, -140)
|
||
local attributeTitle = attributeFrame:CreateFontString(nil, "OVERLAY")
|
||
attributeTitle:SetFont("Fonts\\ZYKai_T.ttf", 14, "OUTLINE")
|
||
attributeTitle:SetPoint("TOP", 0, 0)
|
||
attributeTitle:SetText("属性加成")
|
||
attributeTitle:SetTextColor(1, 0.82, 0)
|
||
SM_Collections.MainFrame.RightSidePanel.AttributeBonusFrame = attributeFrame
|
||
end
|
||
SM_Collections.MainFrame.RightSidePanel.AttributeBonusFrame:Show()
|
||
if not SM_Collections.MainFrame.RightSidePanel.attributeTexts then
|
||
SM_Collections.MainFrame.RightSidePanel.attributeTexts = {}
|
||
end
|
||
end
|
||
|
||
-- 创建一个等待提示
|
||
local waitingText = panel:CreateFontString(nil, "OVERLAY")
|
||
waitingText:SetFont("Fonts\\ZYKai_T.ttf", 16, "OUTLINE")
|
||
waitingText:SetPoint("CENTER", panel, "CENTER", 0, 0)
|
||
waitingText:SetText("正在从服务器获取物品数据...")
|
||
waitingText:SetTextColor(1, 0.82, 0)
|
||
waitingText:Show()
|
||
panel.waitingText = waitingText
|
||
|
||
-- 读取SavedVariables缓存(只判断,不赋值)
|
||
local cacheValid = false
|
||
if SM_CollectionsDB and SM_CollectionsDB.itemCache then
|
||
local cache = SM_CollectionsDB.itemCache
|
||
if cache.items and #cache.items > 0 then
|
||
cacheValid = true
|
||
end
|
||
end
|
||
|
||
if cacheValid then
|
||
if panel.waitingText then panel.waitingText:Hide() end
|
||
self:ProcessAndShowItems(SM_CollectionsDB.itemCache.items, panel)
|
||
else
|
||
-- 请求数据
|
||
for _, slot in ipairs(self.ALL_SLOTS) do
|
||
slot.items = {}
|
||
end
|
||
local slotTypeMap = {}
|
||
for _, slot in ipairs(self.ALL_SLOTS) do
|
||
slotTypeMap[slot.invType] = slot
|
||
end
|
||
function self:GetItemEquipLocFromServerData(serverItemType, nini)
|
||
if slotTypeMap[serverItemType] then
|
||
return slotTypeMap[serverItemType]
|
||
end
|
||
return nil
|
||
end
|
||
SM_Collections.DataManager:GetItems(function(items)
|
||
if panel.waitingText then panel.waitingText:Hide() end
|
||
if items and #items > 0 then
|
||
-- 只在有数据时才写入缓存
|
||
SM_CollectionsDB.itemCache = {
|
||
items = items,
|
||
lastUpdate = time()
|
||
}
|
||
self:ProcessAndShowItems(items, panel)
|
||
else
|
||
-- 没有数据,显示提示
|
||
if panel.waitingText then panel.waitingText:SetText("没有获取到任何物品数据,请检查服务端或本地数据配置!") end
|
||
end
|
||
end)
|
||
end
|
||
return panel
|
||
end
|
||
|
||
function SM_ItemCollectionUI:ProcessAndShowItems(items, panel)
|
||
-- 清空所有槽位的物品数组
|
||
for _, slot in ipairs(self.ALL_SLOTS) do
|
||
slot.items = {}
|
||
end
|
||
-- 创建槽位映射表
|
||
local slotTypeMap = {}
|
||
for _, slot in ipairs(self.ALL_SLOTS) do
|
||
slotTypeMap[slot.invType] = slot
|
||
end
|
||
-- 分类物品到各个槽位
|
||
for i, item in ipairs(items) do
|
||
local itemID = tonumber(item.id)
|
||
if itemID and itemID > 0 then
|
||
local itemEquipLoc = nil
|
||
-- 兼容缓存数据的itemType为中文或invType
|
||
if item.itemType and item.itemType ~= "" then
|
||
if self.typeToInvType and self.typeToInvType[item.itemType] then
|
||
itemEquipLoc = self.typeToInvType[item.itemType]
|
||
else
|
||
itemEquipLoc = item.itemType
|
||
end
|
||
end
|
||
local slotFound = false
|
||
if itemEquipLoc and slotTypeMap[itemEquipLoc] then
|
||
local slot = slotTypeMap[itemEquipLoc]
|
||
local exists = false
|
||
for _, existingID in ipairs(slot.items) do
|
||
if existingID == itemID then exists = true break end
|
||
end
|
||
if not exists then
|
||
table.insert(slot.items, itemID)
|
||
slotFound = true
|
||
end
|
||
end
|
||
if not slotFound then
|
||
print(string.format("[SM_ItemCollectionUI] 警告: 物品 %d (%s) 未找到对应槽位,itemType: %s, 转换后: %s", itemID, item.name or "", tostring(item.itemType), tostring(itemEquipLoc)))
|
||
end
|
||
end
|
||
end
|
||
self:DebugPrintItemArrays()
|
||
self:CreateButtons()
|
||
self:ShowButtons()
|
||
if SM_Collections.MainFrame and SM_Collections.MainFrame.RightSidePanel then
|
||
SM_Collections.MainFrame.RightSidePanel:Show()
|
||
end
|
||
panel:Show()
|
||
if #self.buttons > 0 then
|
||
local firstButton = self.buttons[1]
|
||
self.currentSelectedButton = firstButton
|
||
if firstButton.SelectedTexture then
|
||
firstButton.SelectedTexture:Show()
|
||
end
|
||
self:ShowItemPreview(firstButton.slotData, panel)
|
||
end
|
||
end
|
||
|
||
-- 添加一个调试函数,用于打印物品数组状态
|
||
function SM_ItemCollectionUI:DebugPrintItemArrays()
|
||
|
||
local totalItems = 0
|
||
for i, slot in ipairs(self.ALL_SLOTS) do
|
||
local itemCount = slot.items and #slot.items or 0
|
||
totalItems = totalItems + itemCount
|
||
|
||
-- 如果有物品,打印前三个物品的ID
|
||
if itemCount > 0 then
|
||
local previewItems = {}
|
||
for j = 1, math.min(3, itemCount) do
|
||
local itemName = GetItemInfo(slot.items[j]) or "未知"
|
||
table.insert(previewItems, string.format("%d(%s)", slot.items[j], itemName))
|
||
end
|
||
end
|
||
end
|
||
end
|