WOW_Collection_System/ItemCollection/SM_ItemCollectionUI.lua
2025-07-02 23:35:57 +08:00

1545 lines
64 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 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("属性加成2")
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()
-- 隐藏可能存在的无属性提示文本
if rightSidePanel.noAttributesText then
rightSidePanel.noAttributesText:Hide()
end
-- 显示加载中提示
if not rightSidePanel.loadingText then
rightSidePanel.loadingText = rightSidePanel.attributesContainer:CreateFontString(nil, "OVERLAY")
rightSidePanel.loadingText:SetFont("Fonts\\ZYKai_T.ttf", 12, "OUTLINE")
rightSidePanel.loadingText:SetPoint("TOP", rightSidePanel.attributesContainer, "TOP", 0, -10)
--rightSidePanel.loadingText:SetText("正在加载属性数据...")
rightSidePanel.loadingText:SetTextColor(1, 0.82, 0)
else
rightSidePanel.loadingText:Show()
end
-- 确保DataManager存在
if not SM_Collections.DataManager then
print("[收藏系统] 错误: DataManager未初始化")
if rightSidePanel.loadingText then
rightSidePanel.loadingText:SetText("错误: 数据管理器未初始化")
rightSidePanel.loadingText:SetTextColor(1, 0, 0)
end
return
end
-- 确保GetAttributesForSpecificItem方法存在
if not SM_Collections.DataManager.GetAttributesForSpecificItem then
print("[收藏系统] 错误: GetAttributesForSpecificItem方法未找到")
if rightSidePanel.loadingText then
rightSidePanel.loadingText:SetText("错误: 属性获取方法未找到")
rightSidePanel.loadingText:SetTextColor(1, 0, 0)
end
return
end
-- 从服务端获取物品属性数据
SM_Collections.DataManager:GetAttributesForSpecificItem(itemID, "item", function(attributes)
-- 隐藏加载提示
if rightSidePanel.loadingText then
rightSidePanel.loadingText:Hide()
end
if not attributes or #attributes == 0 then
-- 如果没有属性数据,显示一个提示
if not rightSidePanel.noAttributesText then
rightSidePanel.noAttributesText = rightSidePanel.attributesContainer:CreateFontString(nil, "OVERLAY")
rightSidePanel.noAttributesText:SetFont("Fonts\\ZYKai_T.ttf", 12, "OUTLINE")
rightSidePanel.noAttributesText:SetPoint("TOP", rightSidePanel.attributesContainer, "TOP", 0, -10)
rightSidePanel.noAttributesText:SetText("该物品没有属性加成")
rightSidePanel.noAttributesText:SetTextColor(0.7, 0.7, 0.7)
else
rightSidePanel.noAttributesText:Show()
rightSidePanel.noAttributesText:SetText("该物品没有属性加成")
end
return
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", 30, 0)
nameText:SetFont("Fonts\\ZYKai_T.ttf", 10, "MONOCHROME")
nameText:SetText(attribute.Name or "")
-- 根据物品是否已获得设置文本颜色
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 or "")
-- 根据物品是否已获得设置文本颜色
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)
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() --隐藏NEW图标
-- 从NewItems表中移除
if SM_Collections and SM_Collections.NewItems and SM_Collections.NewItems.item then --如果NewItems表存在且NewItems.item存在
SM_Collections.NewItems.item[tonumber(itemID)] = nil --从NewItems表中移除
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 --如果模型帧数大于0且物品ID大于0
local firstModel = modelFrames[1] --获取第一个模型
self:SelectModel(firstModel) --选中第一个模型
local itemID = slot.items[startIdx] --获取物品ID
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") --设置模型类型
model:Undress() --脱下装备
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.previewFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
pageText:SetPoint("BOTTOM", panel, "BOTTOM", 80, 40)
pageText:SetText(string.format("第 %d / %d 页", self.currentPage, self.totalPages))
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("属性加成1")
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