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

1283 lines
51 KiB
Lua
Raw Permalink 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.

-- SM_UI_SplitPanel.lua
-- 点击处理逻辑
function OnItemClick(button, itemData, itemType, panel)
-- 切换到非物品收藏界面时,隐藏物品收藏的“已获得/未获得”状态文本
if SM_Collections.MainFrame and SM_Collections.MainFrame.RightSidePanel and SM_Collections.MainFrame.RightSidePanel.statusText then
SM_Collections.MainFrame.RightSidePanel.statusText:Hide()
end
-- 设置按钮选中状态
if button then
-- 取消其他按钮的选中状态
if panel and panel.scrollChild and panel.scrollChild.buttons then
for _, otherBtn in ipairs(panel.scrollChild.buttons) do
if otherBtn ~= button then
otherBtn.isSelected = false
if otherBtn.selectedTexture then
otherBtn.selectedTexture:Hide()
end
end
end
end
-- 设置当前按钮为选中状态
button.isSelected = true
if button.selectedTexture then
button.selectedTexture:Show()
end
end
-- 更新名称和描述
if SM_Collections.MainFrame and SM_Collections.MainFrame.RightSidePanel then
-- 获取显示名称(服务端名称或游戏内名称)
local displayName = itemData.name
if not displayName or displayName == "" then
-- 尝试用GetSpellInfo获取名称添加安全调用
local spellName
if itemData.id and type(itemData.id) == "number" and itemData.id > 0 then
local success, result = pcall(function()
return GetSpellInfo(itemData.id)
end)
if success and result then
spellName = result
else
spellName = nil
end
end
if spellName and spellName ~= "" then
displayName = spellName
else
-- 使用默认名称
displayName = "ID: " .. itemData.id
end
end
-- 更新名称
if SM_Collections.MainFrame.RightSidePanel.MountNama then
SM_Collections.MainFrame.RightSidePanel.MountNama:SetText(displayName or "")
SM_Collections.MainFrame.RightSidePanel.MountNama:Show()
end
-- 更新描述
if SM_Collections.MainFrame.RightSidePanel.introText then
SM_Collections.MainFrame.RightSidePanel.introText:SetText(itemData.description or "")
SM_Collections.MainFrame.RightSidePanel.introText:Show()
end
end
-- 更新模型
local creatureDisplayID = nil
-- 如果服务端已经提供了displayID优先使用它
if itemData.displayID and itemData.displayID > 0 then
creatureDisplayID = itemData.displayID
else
-- 否则从映射表中获取
creatureDisplayID = SM_Collections:GetCreatureDisplayID(itemData.id, itemType)
end
if panel and panel.model and creatureDisplayID and creatureDisplayID > 0 then
panel.model:Hide()
panel.model:SetPosition(0, 0, 0)
panel.model.zoomLevel = 0
panel.model:Show()
panel.model:SetCreature(creatureDisplayID)
else
print("无法显示模型: ", panel and "面板存在" or "面板不存在", panel and panel.model and "模型存在" or "模型不存在",
creatureDisplayID and creatureDisplayID > 0 and "有效的显示ID" or "无效的显示ID")
end
-- 更新右侧面板的属性加成
SM_Collections:UpdateRightPanel(itemData, itemType)
-- 添加类型图标和文本
if panel then
SM_Collections:UpdateTypeIcon(panel, itemData, itemType)
end
end
function SM_Collections:CreateSplitPanel(parent, data, itemType)
assert(parent, "CreateSplitPanel: parent is nil!")
local panel = CreateFrame("Frame", "SM_CollectionsPanel", parent)
panel:SetAllPoints()
-- 左侧列表
local listFrame = CreateFrame("Frame", "SM_CollectionslistFrame", panel)
listFrame:SetSize(220, 410)
listFrame:SetPoint("TOPLEFT", 5, -13)
listFrame:SetBackdrop({
bgFile = "Interface\\AddOns\\SM_CollectionSystem\\Textures\\liebiaoditu"
})
local scrollFrameName = "SM_ScrollFrame_" .. itemType .. "_" .. math.random(1000, 9999)
local scrollFrame = CreateFrame("ScrollFrame", scrollFrameName, listFrame, "UIPanelScrollFrameTemplate")
scrollFrame:SetSize(200, 415)
scrollFrame:SetPoint("TOPLEFT", 5, 2)
-- 滚动条装饰
local BackgroundFrame = CreateFrame("Frame", "SM_CollectionsOverlayFrame", scrollFrame)
BackgroundFrame:SetSize(25, 410)
BackgroundFrame:SetPoint("RIGHT", scrollFrame, "RIGHT", 25.5, 1)
BackgroundFrame:SetFrameLevel(scrollFrame:GetFrameLevel() + 1)
local ScrollBarBackground = BackgroundFrame:CreateTexture(nil, "BACKGROUND")
ScrollBarBackground:SetSize(25, 410)
ScrollBarBackground:SetPoint("CENTER", BackgroundFrame, "CENTER", 0, 0)
ScrollBarBackground:SetTexture("Interface\\AddOns\\SM_CollectionSystem\\Textures\\cooldown")
local overlayFrame = CreateFrame("Frame", "SM_CollectionsOverlayFrame", BackgroundFrame)
overlayFrame:SetSize(30, 420)
overlayFrame:SetPoint("CENTER", BackgroundFrame, "CENTER", 0, 1)
overlayFrame:SetFrameLevel(BackgroundFrame:GetFrameLevel() + 10)
local scrollBarOverlay = overlayFrame:CreateTexture(nil, "OVERLAY")
scrollBarOverlay:SetAllPoints(overlayFrame)
scrollBarOverlay:SetTexture("Interface\\AddOns\\SM_CollectionSystem\\Textures\\ScrollFrame")
scrollBarOverlay:SetTexCoord(0, 1, 0, 1)
scrollBarOverlay:SetVertexColor(1, 1, 1, 1)
scrollBarOverlay:SetBlendMode("BLEND")
local scrollChild = CreateFrame("Frame", "SM_CollectionsScrollChild", scrollFrame)
scrollChild:SetSize(300, 1)
scrollFrame:SetScrollChild(scrollChild)
-- 右侧模型显示
local modelFrame = CreateFrame("Frame", "SM_CollectionsModelFrame", parent)
modelFrame:SetSize(380, 430)
modelFrame:SetPoint("CENTER", 30, -3)
modelFrame:SetFrameStrata("HIGH")
modelFrame:SetFrameLevel(parent:GetFrameLevel() + 10)
-- 3D模型
local model = CreateFrame("PlayerModel", "SM_CollectionsModel", modelFrame)
model:SetSize(360, 415)
model:SetPoint("TOP", 5, 0)
model:SetCamera(0)
model:SetFacing(0)
model.zoomLevel = 0
model:SetPosition(0, 0, 0)
model:SetFrameStrata("HIGH")
model:SetFrameLevel(modelFrame:GetFrameLevel() + 1)
-- 记录模型初始位置,用于平移时参考
model.defaultX = 5
model.defaultY = 0
model.offsetX = 0
model.offsetY = 0
model.scale = 1.0
-- 模型控制功能
model:EnableMouse(true)
model:SetScript("OnMouseDown", function(self, button)
if button == "LeftButton" then
self.isRotating = true
self.lastX = GetCursorPosition()
elseif button == "RightButton" then
-- 鼠标右键按下时启用平面移动模式
self.isMoving = true
self.lastX, self.lastY = GetCursorPosition()
end
end)
model:SetScript("OnMouseUp", function(self, button)
if button == "LeftButton" then
self.isRotating = false
elseif button == "RightButton" then
self.isMoving = false
end
end)
-- 添加鼠标滚轮缩放功能
model:EnableMouseWheel(true)
model:SetScript("OnMouseWheel", function(self, delta)
-- delta为1表示向上滚动(放大)delta为-1表示向下滚动(缩小)
local SCALE_STEP = 0.1 -- 缩放步长
-- 根据滚轮方向调整缩放级别
self.scale = self.scale + delta * SCALE_STEP
-- 限制缩放范围,避免过度放大或缩小
if self.scale < 0.01 then self.scale = 0.01 end
if self.scale > 2.0 then self.scale = 2.0 end
-- 应用真正的模型缩放
self:SetModelScale(self.scale)
end)
local ROTATE_SPEED = math.rad(90)
model.isRotatingLeft = false
model.isRotatingRight = false
-- 左旋转按钮
local rotateLeftBtn = CreateFrame("Button", nil, modelFrame)
rotateLeftBtn:SetSize(32, 32)
rotateLeftBtn:SetPoint("BOTTOM", modelFrame, "BOTTOM", -50, 30)
rotateLeftBtn:SetNormalTexture("Interface\\Buttons\\UI-RotationLeft-Button-Up")
rotateLeftBtn:SetPushedTexture("Interface\\Buttons\\UI-RotationLeft-Button-Down")
rotateLeftBtn:SetHighlightTexture("Interface\\Buttons\\UI-RotationLeft-Button-Highlight")
rotateLeftBtn:SetFrameStrata("HIGH")
rotateLeftBtn:SetFrameLevel(modelFrame:GetFrameLevel() + 2)
rotateLeftBtn:SetScript("OnMouseDown", function() model.isRotatingLeft = true end)
rotateLeftBtn:SetScript("OnMouseUp", function() model.isRotatingLeft = false end)
rotateLeftBtn:HookScript("OnLeave", function() model.isRotatingLeft = false end)
-- 右旋转按钮
local rotateRightBtn = CreateFrame("Button", nil, modelFrame)
rotateRightBtn:SetSize(32, 32)
rotateRightBtn:SetPoint("BOTTOM", modelFrame, "BOTTOM", 50, 30)
rotateRightBtn:SetNormalTexture("Interface\\Buttons\\UI-RotationRight-Button-Up")
rotateRightBtn:SetPushedTexture("Interface\\Buttons\\UI-RotationRight-Button-Down")
rotateRightBtn:SetHighlightTexture("Interface\\Buttons\\UI-RotationRight-Button-Highlight")
rotateRightBtn:SetFrameStrata("HIGH")
rotateRightBtn:SetFrameLevel(modelFrame:GetFrameLevel() + 2)
rotateRightBtn:SetScript("OnMouseDown", function() model.isRotatingRight = true end)
rotateRightBtn:SetScript("OnMouseUp", function() model.isRotatingRight = false end)
rotateRightBtn:HookScript("OnLeave", function() model.isRotatingRight = false end)
-- 控制更新
model:SetScript("OnUpdate", function(self, elapsed)
-- 处理旋转
if self.isRotating then
local x = GetCursorPosition()
local delta = (x - (self.lastX or x)) * 0.01
self.lastX = x
self:SetFacing(self:GetFacing() + delta)
end
if self.isRotatingLeft then
self:SetFacing(self:GetFacing() + ROTATE_SPEED * elapsed)
elseif self.isRotatingRight then
self:SetFacing(self:GetFacing() - ROTATE_SPEED * elapsed)
end
-- 处理屏幕平面移动(鼠标右键)
if self.isMoving then
local x, y = GetCursorPosition()
local deltaX = (x - (self.lastX or x)) * 0.5
local deltaY = (y - (self.lastY or y)) * 0.5
self.lastX, self.lastY = x, y
-- 更新平移偏移量
self.offsetX = self.offsetX + deltaX
self.offsetY = self.offsetY + deltaY -- 修改符号,修复方向问题
-- 限制移动范围
self.offsetX = math.max(-100, math.min(100, self.offsetX))
self.offsetY = math.max(-100, math.min(100, self.offsetY))
-- 应用新位置到模型的屏幕位置
self:ClearAllPoints()
self:SetPoint("TOP", modelFrame, "TOP", self.defaultX + self.offsetX, self.defaultY + self.offsetY)
end
end)
-- UI元素 - 移除重复的文本显示
local nameText = modelFrame:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
nameText:SetPoint("BOTTOM", modelFrame, "BOTTOM", 0, 80) -- 将名称移到模型下方,避免与模型重叠
nameText:SetTextColor(1, 1, 1)
nameText:SetWidth(320) -- 限制宽度避免文本溢出
nameText:SetHeight(0) -- 自动调整高度
nameText:SetJustifyH("CENTER")
-- 描述文本不在模型框架中显示,让右侧面板来显示
local descText = modelFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
descText:SetSize(320, 0) -- 自动高度
descText:SetPoint("TOP", nameText, "BOTTOM", 0, -5) -- 放在名称下方
descText:SetJustifyH("CENTER")
descText:Hide() -- 隐藏这个文本,我们将使用右侧面板的文本
panel.listFrame = listFrame
panel.scrollChild = scrollChild
panel.modelFrame = modelFrame
panel.model = model
panel.nameText = nameText
panel.descText = descText
-- 对数据进行排序,将已获得的项目排在前面
table.sort(data, function(a, b)
if a.obtained and not b.obtained then
return true
elseif not a.obtained and b.obtained then
return false
else
-- 如果获得状态相同按ID排序
return a.id < b.id
end
end)
-- 创建列表项
self:CreateListItems(scrollChild, data, itemType, model, nameText, descText)
-- 设置初始选中项:优先选择已获得的物品,如果没有则选择第一个
if scrollChild.obtainedButtons and #scrollChild.obtainedButtons > 0 then
-- 随机选择一个已获得的物品
local randomIndex = math.random(1, #scrollChild.obtainedButtons)
local selectedButton = scrollChild.obtainedButtons[randomIndex]
-- 手动触发点击事件
if selectedButton and selectedButton.itemData then
OnItemClick(selectedButton, selectedButton.itemData, itemType, panel)
end
elseif scrollChild.buttons and #scrollChild.buttons > 0 then
-- 如果没有已获得的物品,选择第一个
local firstButton = scrollChild.buttons[1]
-- 手动触发点击事件
if firstButton and firstButton.itemData then
OnItemClick(firstButton, firstButton.itemData, itemType, panel)
end
end
-- 绑定当前panel便于切换标签时只隐藏panel不隐藏模型区
if self.CurrentPanel then
self.CurrentPanel:Hide()
end
self.CurrentPanel = panel
return panel
end
function SM_Collections:CreateListItems(parent, data, itemType, model, nameText, descText)
local buttonW = 170
local buttonHeight = 40
local spacing = 2
local iconSize = 30
if itemType == "card" then
buttonW = 200
end
-- 存储所有按钮的引用,以便后续选中操作
local buttons = {}
local obtainedButtons = {}
for i, item in ipairs(data) do
local button = CreateFrame("Button", "Collectionsbutton" .. i, parent)
button:SetSize(buttonW, buttonHeight)
button:SetPoint("TOPLEFT", 30, -(i - 1) * (buttonHeight + spacing))
button:SetNormalTexture("Interface\\AddOns\\SM_CollectionSystem\\Textures\\liebiaoditu_kuang_A")
button:SetHighlightTexture("Interface\\AddOns\\SM_CollectionSystem\\Textures\\liebiaoditu_kuang_B")
-- 添加选中状态纹理
local selectedTexture = button:CreateTexture(nil, "OVERLAY")
selectedTexture:SetAllPoints(button)
selectedTexture:SetTexture("Interface\\AddOns\\SM_CollectionSystem\\Textures\\liebiaoditu_kuang_C")
selectedTexture:SetBlendMode("ADD")
--selectedTexture:SetVertexColor(0, 1, 1, 1) -- 金黄色高亮
selectedTexture:Hide()
button.selectedTexture = selectedTexture
-- 存储物品数据和选中状态
button.itemData = item
button.isSelected = false
button.itemType = itemType -- 添加itemType属性用于推断面板类型
-- 添加"NEW"标记,如果这个项目是新获得的
if item.obtained and self.NewItems and self.NewItems[itemType] and self.NewItems[itemType][item.id] then
-- 检查是否已经有NEW标记
if not button.newTexture then
local newTexture = button:CreateTexture(nil, "OVERLAY")
newTexture:SetSize(32, 28)
newTexture:SetPoint("TOPRIGHT", button, "TOPRIGHT", 10, 10)
newTexture:SetTexture("Interface\\AddOns\\SM_CollectionSystem\\Textures\\New_Icon")
button.newTexture = newTexture
-- 先清除现有的鼠标处理函数,防止多次注册
button:SetScript("OnEnter", nil)
-- 使用SetScript而不是HookScript确保只有一个处理函数
button:SetScript("OnEnter", function(self)
if self.newTexture and self.newTexture:IsShown() then
self.newTexture:Hide()
-- 从NewItems表中移除
if SM_Collections.NewItems and SM_Collections.NewItems[itemType] then
SM_Collections.NewItems[itemType][item.id] = nil
end
end
-- 显示提示信息
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
if self.itemData then
GameTooltip:SetText(self.itemData.name or "未知物品")
else
GameTooltip:SetText("收藏项目")
end
GameTooltip:Show()
-- 显示高亮
if self.Highlight then
self.Highlight:Show()
end
end)
button:SetScript("OnLeave", function(self)
GameTooltip:Hide()
if self.Highlight then
self.Highlight:Hide()
end
end)
else
-- 如果已经有NEW标记确保它是可见的
button.newTexture:Show()
end
end
local ButtonIcon = nil
if itemType == "mount" or itemType == "companion" then
ButtonIcon = CreateFrame("Button", "CollectionsButtonIcon" .. i, button)
ButtonIcon:SetSize(iconSize, iconSize)
ButtonIcon:SetPoint("RIGHT", button, "LEFT", 0, 0)
-- 安全地调用GetSpellInfo
local name, rank, icon
if item.id and type(item.id) == "number" and item.id > 0 then
local success, result = pcall(function()
return GetSpellInfo(item.id)
end)
if success and result then
name = result
_, _, icon = GetSpellInfo(item.id) -- 再次调用获取图标
else
name = nil
icon = nil
end
end
if icon then
ButtonIcon:SetNormalTexture(icon)
ButtonIcon:SetHighlightTexture(icon)
-- 为未获得的项目设置灰色图标
if not item.obtained then
local normalTexture = ButtonIcon:GetNormalTexture()
if normalTexture then
normalTexture:SetDesaturated(true)
normalTexture:SetVertexColor(0.5, 0.5, 0.5)
end
local highlightTexture = ButtonIcon:GetHighlightTexture()
if highlightTexture then
highlightTexture:SetDesaturated(true)
highlightTexture:SetVertexColor(0.7, 0.7, 0.7)
end
end
else
ButtonIcon:SetNormalTexture("Interface\\Icons\\INV_Misc_QuestionMark")
ButtonIcon:SetHighlightTexture("Interface\\Icons\\INV_Misc_QuestionMark")
-- 为未获得的项目设置灰色问号图标
if not item.obtained then
local normalTexture = ButtonIcon:GetNormalTexture()
if normalTexture then
normalTexture:SetDesaturated(true)
normalTexture:SetVertexColor(0.5, 0.5, 0.5)
end
local highlightTexture = ButtonIcon:GetHighlightTexture()
if highlightTexture then
highlightTexture:SetDesaturated(true)
highlightTexture:SetVertexColor(0.7, 0.7, 0.7)
end
end
end
ButtonIcon:SetFrameLevel(button:GetFrameLevel() + 1)
ButtonIcon:SetScript("OnEnter", function()
GameTooltip:SetOwner(ButtonIcon, "ANCHOR_RIGHT")
-- 安全地设置技能链接
if item.id and type(item.id) == "number" and item.id > 0 then
local success, errorMsg = pcall(function()
GameTooltip:SetHyperlink("spell:" .. item.id)
end)
if not success then
-- 如果SetHyperlink失败使用SetText替代
GameTooltip:SetText(item.name or ("ID: " .. item.id))
end
else
GameTooltip:SetText(item.name or "未知物品")
end
GameTooltip:Show()
end)
ButtonIcon:SetScript("OnLeave", function() GameTooltip:Hide() end)
ButtonIcon:Show()
end
local text = button:CreateFontString(nil, "OVERLAY", "GameFontNormal")
if itemType == "card" then
button:SetPoint("TOPLEFT", 0, -(i - 1) * (buttonHeight + spacing))
text:SetPoint("CENTER", 0, 0)
else
text:SetPoint("LEFT", 10, 0)
end
-- 名称显示优先级:服务端名称 > GetSpellInfo名称 > 默认名称
local displayName = item.name
if not displayName or displayName == "" then
-- 尝试用GetSpellInfo获取名称添加安全调用
local spellName
if item.id and type(item.id) == "number" and item.id > 0 then
local success, result = pcall(function()
return GetSpellInfo(item.id)
end)
if success and result then
spellName = result
else
spellName = nil
end
end
if spellName and spellName ~= "" then
displayName = spellName
else
-- 使用默认名称
displayName = "ID: " .. item.id
end
end
--
text:SetText(displayName)
text:SetTextColor(item.obtained and 1 or 0.5, item.obtained and 1 or 0.5, item.obtained and 1 or 0.5)
-- 保存文本对象的引用,以便后续更新
button.text = text
-- 选中处理函数
local function selectButton(btn)
-- 取消其他按钮的选中状态
for _, otherBtn in ipairs(buttons) do
if otherBtn ~= btn then
otherBtn.isSelected = false
otherBtn.selectedTexture:Hide()
end
end
-- 设置当前按钮为选中状态
btn.isSelected = true
btn.selectedTexture:Show()
-- 更新模型和信息
local panel = self.CurrentPanel
OnItemClick(btn, btn.itemData, itemType, panel)
end
-- 列表按钮单击
button:SetScript("OnClick", function()
selectButton(button)
end)
--列表按钮双击
button:SetScript("OnDoubleClick", function()
-- 根据itemType发送不同的消息
if itemType == "mount" then
SendAddonMessage("SM_C_SUMMON_MOUNT", item.id .. " " .. 1, "GUILD")
elseif itemType == "companion" then
SendAddonMessage("SM_C_SUMMON_COMPANION", item.id .. " " .. 1, "GUILD")
elseif itemType == "card" then
SendAddonMessage("SM_C_USE_CARD", item.id, "GUILD")
elseif itemType == "item" then
SendAddonMessage("SM_C_VIEW_ITEM", item.id, "GUILD")
end
end)
-- 在鼠标悬停时在工具提示中显示获得状态
button:SetScript("OnEnter", function()
GameTooltip:SetOwner(button, "ANCHOR_RIGHT")
-- 使用之前计算的displayName而不是直接使用item.name
GameTooltip:SetText(displayName or "未知物品")
local statusText = item.obtained and "|cFF00FF00已获得|r" or "|cFFFF0000未获得|r"
GameTooltip:AddLine(statusText)
GameTooltip:Show()
end)
button:SetScript("OnLeave", function()
GameTooltip:Hide()
end)
button:Show()
-- 添加到按钮列表
table.insert(buttons, button)
-- 如果是已获得的物品,添加到已获得列表
if item.obtained then
table.insert(obtainedButtons, button)
end
end
-- 设置初始选中项:优先选择已获得的物品,如果没有则选择第一个
if #obtainedButtons > 0 then
-- 随机选择一个已获得的物品
local randomIndex = math.random(1, #obtainedButtons)
local selectedButton = obtainedButtons[randomIndex]
selectedButton.isSelected = true
selectedButton.selectedTexture:Show()
-- 更新模型和信息
local panel = self.CurrentPanel
OnItemClick(selectedButton, selectedButton.itemData, itemType, panel)
elseif #buttons > 0 then
-- 如果没有已获得的物品,选择第一个
local firstButton = buttons[1]
firstButton.isSelected = true
firstButton.selectedTexture:Show()
-- 更新模型和信息
local panel = self.CurrentPanel
OnItemClick(firstButton, firstButton.itemData, itemType, panel)
end
local totalHeight = #data * (buttonHeight + spacing)
parent:SetHeight(math.max(totalHeight, 1))
-- 保存按钮引用到面板中,以便后续访问
parent.buttons = buttons
parent.obtainedButtons = obtainedButtons
end
function SM_Collections:UpdateRightPanel(selectedItem, itemType)
if not self.MainFrame or not self.MainFrame.RightSidePanel then
return
end
local rightPanel = self.MainFrame.RightSidePanel
--
-- 更新坐骑名称
if rightPanel.MountNama then
-- 获取显示名称
local displayName = selectedItem.name
if not displayName or displayName == "" then
local spellName = GetSpellInfo(selectedItem.id)
displayName = spellName or "ID: " .. selectedItem.id
end
--
rightPanel.MountNama:SetText(displayName or "")
rightPanel.MountNama:Show()
-- 检查文本框的各种属性
--
-- "层级=", rightPanel.MountNama:GetDrawLayer(),
-- "宽高=", rightPanel.MountNama:GetWidth(), rightPanel.MountNama:GetHeight(),
-- "位置=", rightPanel.MountNama:GetPoint())
else
end
-- 更新描述文本并确保正确换行
if rightPanel.introText then
rightPanel.introText:SetText(selectedItem.description or "")
rightPanel.introText:SetHeight(0) -- 重置高度以便自动计算
end
-- 显示属性加成
if rightPanel.AttributeBonusFrame then
self:UpdateAttributesForItem(selectedItem, rightPanel.AttributeBonusFrame, itemType)
end
end
-- 更新属性加成
function SM_Collections:UpdateAttributesForItem(item, parentFrame, itemType)
local children = { parentFrame:GetChildren() }
for _, child in ipairs(children) do
if child:GetName() and string.find(child:GetName(), "SM_CollectionsAttributeutton") then
child:Hide()
end
end
-- 清理物品收藏使用的属性文本
if self.MainFrame and self.MainFrame.RightSidePanel and self.MainFrame.RightSidePanel.attributeTexts then
for _, text in ipairs(self.MainFrame.RightSidePanel.attributeTexts) do
text:Hide()
end
end
self:GetAttributesForItem(item, function(attributes)
if #attributes == 0 then
parentFrame:Hide()
return
end
parentFrame:Show()
local buttonH = 150
local buttonW = 20
for i, attribute in ipairs(attributes) do
local AttributeName = attribute.Name
local AttributeValue = attribute.value
local isPositive = attribute.isPositive
local button = CreateFrame("Button", "SM_CollectionsAttributeutton" .. i, parentFrame)
button:SetSize(buttonH, buttonW)
button:SetNormalTexture("Interface\\AddOns\\SM_CollectionSystem\\Textures\\AttributeuttonTexture")
button:SetPoint("TOPLEFT", 0, -30 - (i - 1) * (buttonW))
local nameText = button:CreateFontString(nil, "OVERLAY")
nameText:SetPoint("CENTER", 0, 0)
nameText:SetFont("Fonts\\ZYKai_T.ttf", 10, "MONOCHROME")
nameText:SetText(AttributeName)
-- 根据物品是否获得设置文本颜色
if item.obtained 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")
local formattedValue = isPositive and ("+ " .. AttributeValue) or ("- " .. AttributeValue)
valueText:SetText(formattedValue)
-- 根据物品是否获得设置属性值颜色
if item.obtained then
-- 已获得:根据属性是正面还是负面设置颜色
valueText:SetTextColor(isPositive and 0 or 1, isPositive and 1 or 0, 0)
else
-- 未获得:灰色
valueText:SetTextColor(0.5, 0.5, 0.5)
end
button:Show()
end
end, itemType)
end
function SM_Collections:GetAttributesForItem(item, callback, itemType)
SM_Collections.DataManager:GetAttributesForSpecificItem(item.id, itemType, function(attributes)
callback(attributes)
end)
end
-- 更新类型图标
function SM_Collections:UpdateTypeIcon(panel, item, itemType)
if not panel or not panel.model then return end
local typeIcon = self:CreateTypeIcon(panel)
if not item then
typeIcon:Hide()
return
end
-- 根据不同类型设置图标和文本
if itemType == "mount" then
-- 确定坐骑类型:飞行、陆地、水下
local mountType = item.mountType or "陆地"
local icon = "Interface\\ICONS\\Ability_Mount_RidingHorse"
if item.canFly then
mountType = "飞行"
icon = "Interface\\ICONS\\Ability_Mount_FlyingCarpet"
elseif item.canSwim then
mountType = "水下"
icon = "Interface\\ICONS\\Ability_Mount_SeaTurtle"
end
SetPortraitToTexture(typeIcon.icon, icon) -- 圆形肖像
typeIcon.typeText:SetText(mountType)
elseif itemType == "companion" then
-- 确定宠物类型:野兽、元素、人形等
local petType = item.petType or "野兽"
local icon = "Interface\\ICONS\\Ability_Hunter_BeastCall"
if petType == "元素" then
icon = "Interface\\ICONS\\INV_Elemental_Crystal_Fire"
elseif petType == "人形" then
icon = "Interface\\ICONS\\INV_Misc_Head_Human_01"
elseif petType == "亡灵" then
icon = "Interface\\ICONS\\Spell_Shadow_AnimateDead"
elseif petType == "机械" then
icon = "Interface\\ICONS\\INV_Misc_Toy_07"
end
SetPortraitToTexture(typeIcon.icon, icon) -- 圆形肖像
typeIcon.typeText:SetText(petType)
elseif itemType == "card" then
-- 卡牌类型判断
local cardType = "普通"
local icon = "Interface\\ICONS\\INV_Misc_Book_07"
-- 1. 首先检查item.cardType如果服务器提供了类型信息优先使用
if item.cardType then
cardType = item.cardType
-- 根据cardType设置对应的图标
if cardType == "精英" then
icon = "Interface\\ICONS\\Ability_Warrior_ChallengingShout"
elseif cardType == "稀有" then
icon = "Interface\\ICONS\\INV_Misc_Gem_Pearl_05"
elseif cardType == "世界BOSS" then
icon = "Interface\\ICONS\\Ability_Creature_Cursed_05"
end
-- 2. 如果没有cardType我们可以尝试从名称或描述中推断
else
-- 检查名称或描述中是否包含关键词
local name = item.name or ""
local desc = item.description or ""
local combinedText = name .. " " .. desc
-- 转换为小写以便不区分大小写匹配
combinedText = string.lower(combinedText)
-- 检查关键词
if string.find(combinedText, "首领") or
string.find(combinedText, "boss") or
string.find(combinedText, "世界boss") or
string.find(combinedText, "团队boss") then
cardType = "世界BOSS"
icon = "Interface\\ICONS\\Ability_Creature_Cursed_05"
elseif string.find(combinedText, "稀有") or
string.find(combinedText, "rare") then
cardType = "稀有"
icon = "Interface\\ICONS\\INV_Misc_Gem_Pearl_05"
elseif string.find(combinedText, "精英") or
string.find(combinedText, "elite") then
cardType = "精英"
icon = "Interface\\ICONS\\Ability_Warrior_ChallengingShout"
end
end
-- 3. 如果服务器提供了自定义类型数据,可以在这里添加处理逻辑
-- 例如item.customType, item.creatureFlags 等
SetPortraitToTexture(typeIcon.icon, icon) -- 圆形肖像
typeIcon.typeText:SetText(cardType)
end
typeIcon:Show()
end
-- 创建类型图标
function SM_Collections:CreateTypeIcon(panel)
if not panel.typeIcon then
local typeIcon = CreateFrame("Frame", nil, panel.model)
typeIcon:SetSize(40, 40)
typeIcon:SetPoint("TOPRIGHT", panel.model, "TOPRIGHT", -10, -10)
-- 创建外框纹理
local border = typeIcon:CreateTexture(nil, "OVERLAY")
border:SetSize(38, 38)
border:SetPoint("CENTER", typeIcon, "CENTER", 0, 0)
border:SetTexture("Interface\\AddOns\\SM_CollectionSystem\\Textures\\Cir_Overlay")
typeIcon.border = border
-- 创建图标
local icon = typeIcon:CreateTexture(nil, "BACKGROUND")
icon:SetSize(30, 30)
icon:SetPoint("CENTER", typeIcon, "CENTER", 0, 0)
typeIcon.icon = icon
-- 创建文本
local typeText = typeIcon:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
typeText:SetPoint("BOTTOM", icon, "BOTTOM", 0, -15)
typeText:SetTextColor(1, 1, 1)
typeIcon.typeText = typeText
panel.typeIcon = typeIcon
end
return panel.typeIcon
end
-- 刷新收藏状态
function SM_Collections:RefreshCollectionStatus(itemType, itemID, isObtained)
-- 如果当前没有显示面板,不需要刷新
if not self.CurrentPanel or not self.CurrentPanel.scrollChild then
return
end
local buttons = self.CurrentPanel.scrollChild.buttons
if not buttons then
return
end
-- 检查当前是否显示了对应类型的面板
local isCorrectPanel = false
-- 尝试从当前面板的按钮数据推断面板类型
local inferredPanelType = nil
if #buttons > 0 and buttons[1].itemData then
-- 检查第一个按钮的数据类型
local firstButtonData = buttons[1].itemData
-- 可以检查buttons[1].itemType如果存在的话
if buttons[1].itemType then
inferredPanelType = buttons[1].itemType
end
end
-- 如果是小伙伴类型,特殊处理
if itemType == "companion" then
-- 检查是否有任何按钮的ID匹配
for _, button in ipairs(buttons) do
if button.itemData and button.itemData.id == itemID then
isCorrectPanel = true
break
end
end
end
-- 如果是卡牌类型,也进行特殊处理
if itemType == "card" then
-- 检查是否有任何按钮的ID匹配
for _, button in ipairs(buttons) do
if button.itemData and button.itemData.id == itemID then
isCorrectPanel = true
break
end
end
end
-- 如果MainFrame.tabID存在使用它否则尝试使用推断的面板类型
if not isCorrectPanel and self.MainFrame and self.MainFrame.tabID then
if (itemType == "mount" and self.MainFrame.tabID == 1) or
(itemType == "companion" and self.MainFrame.tabID == 2) or
(itemType == "card" and self.MainFrame.tabID == 3) or
(itemType == "item" and self.MainFrame.tabID == 4) then
isCorrectPanel = true
end
elseif not isCorrectPanel and inferredPanelType and itemType == inferredPanelType then
-- 如果推断出的面板类型与更新的项目类型匹配
isCorrectPanel = true
elseif not isCorrectPanel then
-- 尝试直接检查按钮数据是否包含要更新的项目ID
for _, button in ipairs(buttons) do
if button.itemData and button.itemData.id == itemID then
isCorrectPanel = true
break
end
end
end
if not isCorrectPanel then
-- 如果是物品类型且确实需要刷新
if itemType == "item" then
-- 尝试更新物品模型边框
self:RefreshItemModelBorders(itemID, isObtained)
end
return
end
-- 查找对应的按钮并更新状态
local updatedButton = nil
local buttonFound = false
for i, button in ipairs(buttons) do
if button.itemData and button.itemData.id == itemID then
buttonFound = true
-- 更新获取状态
button.itemData.obtained = isObtained
-- 更新文本颜色
if button.text then
-- 使用保存的文本对象引用
button.text:SetTextColor(isObtained and 1 or 0.5, isObtained and 1 or 0.5, isObtained and 1 or 0.5)
else
-- 尝试获取文本对象
local text = button:GetRegions()
if text and text:GetObjectType() == "FontString" then
text:SetTextColor(isObtained and 1 or 0.5, isObtained and 1 or 0.5, isObtained and 1 or 0.5)
end
end
-- 更新图标颜色(针对坐骑和小伙伴)
for _, child in ipairs({ button:GetChildren() }) do
if child:GetName() and string.find(child:GetName(), "CollectionsButtonIcon") then
local normalTexture = child:GetNormalTexture()
local highlightTexture = child:GetHighlightTexture()
if normalTexture then
if isObtained then
normalTexture:SetDesaturated(false)
normalTexture:SetVertexColor(1, 1, 1)
else
normalTexture:SetDesaturated(true)
normalTexture:SetVertexColor(0.5, 0.5, 0.5)
end
end
if highlightTexture then
if isObtained then
highlightTexture:SetDesaturated(false)
highlightTexture:SetVertexColor(1, 1, 1)
else
highlightTexture:SetDesaturated(true)
highlightTexture:SetVertexColor(0.7, 0.7, 0.7)
end
end
break
end
end
-- 如果是新获得的项目,添加"NEW"标记
if isObtained and self.NewItems and self.NewItems[itemType] and self.NewItems[itemType][itemID] then
-- 检查是否已经有NEW标记
if not button.newTexture then
local newTexture = button:CreateTexture(nil, "OVERLAY")
newTexture:SetSize(32, 28)
newTexture:SetPoint("TOPRIGHT", button, "TOPRIGHT", -10, 10)
newTexture:SetTexture("Interface\\AddOns\\SM_CollectionSystem\\Textures\\New_Icon")
button.newTexture = newTexture
-- 先清除现有的鼠标处理函数,防止多次注册
button:SetScript("OnEnter", nil)
-- 使用SetScript而不是HookScript确保只有一个处理函数
button:SetScript("OnEnter", function(self)
if self.newTexture and self.newTexture:IsShown() then
self.newTexture:Hide()
-- 从NewItems表中移除
if SM_Collections.NewItems and SM_Collections.NewItems[itemType] then
SM_Collections.NewItems[itemType][itemID] = nil
end
end
-- 显示提示信息
GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
if self.itemData then
GameTooltip:SetText(self.itemData.name or "未知物品")
else
GameTooltip:SetText("收藏项目")
end
GameTooltip:Show()
-- 显示高亮
if self.Highlight then
self.Highlight:Show()
end
end)
button:SetScript("OnLeave", function(self)
GameTooltip:Hide()
if self.Highlight then
self.Highlight:Hide()
end
end)
else
-- 如果已经有NEW标记确保它是可见的
button.newTexture:Show()
end
end
-- 如果是当前选中的按钮,更新右侧面板
if button.isSelected then
updatedButton = button
end
-- 更新已获得按钮列表
local obtainedButtons = self.CurrentPanel.scrollChild.obtainedButtons or {}
if isObtained then
-- 添加到已获得列表
local found = false
for i, btn in ipairs(obtainedButtons) do
if btn == button then
found = true
break
end
end
if not found then
table.insert(obtainedButtons, button)
end
else
-- 从已获得列表中移除
for i, btn in ipairs(obtainedButtons) do
if btn == button then
table.remove(obtainedButtons, i)
break
end
end
end
self.CurrentPanel.scrollChild.obtainedButtons = obtainedButtons
-- 重新排序按钮
self:ResortCollectionButtons(self.CurrentPanel.scrollChild, itemType)
break
end
end
-- 如果我们需要更新右侧面板
if updatedButton and updatedButton.isSelected and self.MainFrame and self.MainFrame.RightSidePanel then
-- 更新状态文本
if self.MainFrame.RightSidePanel.statusText then
local statusText = isObtained and "|cFF00FF00已获得11111|r" or "|cFFFF0000未获得22222|r"
self.MainFrame.RightSidePanel.statusText:SetText(statusText)
end
-- 更新属性文本颜色
if self.MainFrame.RightSidePanel.attributesContainer then
for _, child in ipairs({self.MainFrame.RightSidePanel.attributesContainer:GetChildren()}) do
if child:IsObjectType("FontString") then
child:SetTextColor(isObtained and 1 or 0.5, isObtained and 1 or 0.5, isObtained and 1 or 0.5)
end
end
end
end
-- 通知玩家
if isObtained then
local typeName = itemType == "mount" and "坐骑" or itemType == "companion" and "小伙伴" or itemType == "card" and "卡牌" or
"物品"
local itemName = ""
-- 尝试获取物品名称
if updatedButton and updatedButton.itemData then
itemName = updatedButton.itemData.name or ""
end
-- 显示通知
if itemName and itemName ~= "" then
else
end
-- 播放获得音效
PlaySound("UI_EpicLootWon")
-- 应用属性加成 - 请求服务器重新应用属性
SendAddonMessage("SM_C_APPLY_BONUS", itemType .. "|" .. itemID, "WHISPER", UnitName("player"))
end
end
-- 新增函数:更新物品模型边框颜色
function SM_Collections:RefreshItemModelBorders(itemID, isObtained)
if not SM_ItemCollectionUI then return end
-- 遍历所有显示中的物品模型
local previewFrame = SM_ItemCollectionUI.previewFrame
if not previewFrame then return end
for _, child in ipairs({previewFrame:GetChildren()}) do
-- 检查是DressUpModel类型3D模型还是Frame类型图标
local isModelFrame = child:IsObjectType("DressUpModel")
local isIconFrame = child:IsObjectType("Frame") and not child:IsObjectType("DressUpModel")
if (isModelFrame or isIconFrame) and child.itemData and child.itemData.id == itemID then
-- 更新物品数据
child.itemData.obtained = isObtained
-- 更新边框颜色
if child.Border then
if isObtained then
child.Border:SetVertexColor(0, 1, 0, 1) -- 绿色边框
else
child.Border:SetVertexColor(1, 0, 0, 1) -- 红色边框
end
end
-- 如果是新获得的物品且已获得,添加"NEW"标记
if isObtained and self.NewItems and self.NewItems.item and self.NewItems.item[itemID] then
-- 使用SM_ItemCollectionUI的统一处理函数
if SM_ItemCollectionUI and SM_ItemCollectionUI.HandleNewItemIcon then
SM_ItemCollectionUI:HandleNewItemIcon(child, itemID)
end
end
-- 对于图标类物品(颈部、戒指、饰品),更新图标灰度
if isIconFrame then
for _, texture in ipairs({child:GetRegions()}) do
if texture:IsObjectType("Texture") and texture:GetDrawLayer() == "ARTWORK" then
-- 这可能是物品图标
if isObtained then
texture:SetDesaturated(false)
texture:SetVertexColor(1, 1, 1)
else
texture:SetDesaturated(true)
texture:SetVertexColor(0.7, 0.7, 0.7)
end
end
end
end
-- 更新高光颜色
local highlightTextures = { child:GetRegions() }
for _, region in ipairs(highlightTextures) do
if region:GetDrawLayer() == "HIGHLIGHT" then
if isObtained then
region:SetVertexColor(0, 1, 0, 0.7) -- 绿色高光
else
region:SetVertexColor(1, 0, 0, 0.7) -- 红色高光
end
end
end
-- 如果此模型当前被选中,更新右侧面板
if child.isSelected and SM_Collections.MainFrame and SM_Collections.MainFrame.RightSidePanel then
-- 更新状态文本
if SM_Collections.MainFrame.RightSidePanel.statusText then
local statusText = isObtained and "|cFF00FF00已获得|r" or "|cFFFF0000未获得|r"
SM_Collections.MainFrame.RightSidePanel.statusText:SetText(statusText)
end
-- 更新属性文本颜色
if SM_Collections.MainFrame.RightSidePanel.attributesContainer then
for _, child in ipairs({SM_Collections.MainFrame.RightSidePanel.attributesContainer:GetChildren()}) do
if child:IsObjectType("FontString") then
child:SetTextColor(isObtained and 1 or 0.5, isObtained and 1 or 0.5, isObtained and 1 or 0.5)
end
end
end
end
end
end
end
-- 重新排序收藏按钮
function SM_Collections:ResortCollectionButtons(scrollChild, itemType)
if not scrollChild or not scrollChild.buttons then
return
end
local buttons = scrollChild.buttons
-- 按照已获得状态排序:已获得的排在前面
table.sort(buttons, function(a, b)
if a.itemData and b.itemData then
if a.itemData.obtained and not b.itemData.obtained then
return true -- a排在b前面
elseif not a.itemData.obtained and b.itemData.obtained then
return false -- b排在a前面
else
-- 如果获得状态相同按名称或ID排序
if a.itemData.name and b.itemData.name then
return a.itemData.name < b.itemData.name
else
return a.itemData.id < b.itemData.id
end
end
end
return false
end)
-- 重新设置位置
local buttonHeight = 40
local spacing = 2
for i, button in ipairs(buttons) do
button:ClearAllPoints()
-- 根据不同类型设置不同的位置
if itemType == "card" then
-- 卡牌类型使用特殊的位置设置
button:SetPoint("TOPLEFT", 0, -(i - 1) * (buttonHeight + spacing))
else
-- 其他类型使用标准位置设置
button:SetPoint("TOPLEFT", 30, -(i - 1) * (buttonHeight + spacing))
end
end
-- 强制滚动到顶部显示已获得的物品
if scrollChild:GetParent() and scrollChild:GetParent().ScrollBar then
scrollChild:GetParent().ScrollBar:SetValue(0)
end
end
-- 注册事件处理
function SM_Collections:RegisterCollectionEvents()
-- 监听收藏状态更新事件
self:RegisterEvent("ADDON_MESSAGE_PREFIX_SM_S_COLLECTION_UPDATE", function(prefix, message)
local data = self:MessageSplit(message, "|")
if #data >= 3 then
local itemType = data[1]
local itemID = tonumber(data[2])
local isObtained = (data[3] == "1")
if itemID and itemType then
self:RefreshCollectionStatus(itemType, itemID, isObtained)
end
end
end)
end