Files
Nanami-UI/GameMenu.lua
rucky ec9e3c29d6 完成多出修改
修复拾取界面点击无效问题
修复宠物训练界面不显示训练点问题
新增天赋分享到聊天界面
修复飞行界面无法关闭问题
修复术士宠物的显示问题
为天赋界面添加默认数据库支持
框架现在也可自主选择是否启用
玩家框架和目标框架可取消显示3D头像以及透明度修改
背包和银行也添加透明度自定义支持
优化tooltip性能和背包物品显示方式
修复布局模式在ui缩放后不能正常定位的问题
添加硬核模式危险和死亡的工会通报
添加拾取和已拾取的框体
等等
2026-03-23 10:25:25 +08:00

363 lines
13 KiB
Lua

--------------------------------------------------------------------------------
-- Nanami-UI: Game Menu (GameMenu.lua)
-- Reskins the ESC menu (GameMenuFrame) with pink cat-paw theme
--------------------------------------------------------------------------------
SFrames.GameMenu = {}
local GM = SFrames.GameMenu
--------------------------------------------------------------------------------
-- Theme: Pink Cat-Paw
--------------------------------------------------------------------------------
local T = SFrames.ActiveTheme
local BUTTON_W = 170
local BUTTON_H = 26
local BUTTON_GAP = 5
local SIDE_PAD = 16
local HEADER_H = 32
--------------------------------------------------------------------------------
-- Helpers
--------------------------------------------------------------------------------
local function GetFont()
if SFrames and SFrames.GetFont then return SFrames:GetFont() end
return "Fonts\\ARIALN.TTF"
end
local function SetRoundBackdrop(frame, bgColor, borderColor)
frame:SetBackdrop({
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
tile = true, tileSize = 16, edgeSize = 14,
insets = { left = 3, right = 3, top = 3, bottom = 3 },
})
local bg = bgColor or T.panelBg
local bd = borderColor or T.panelBorder
frame:SetBackdropColor(bg[1], bg[2], bg[3], bg[4] or 1)
frame:SetBackdropBorderColor(bd[1], bd[2], bd[3], bd[4] or 1)
end
local function CreateShadow(parent, size)
local s = CreateFrame("Frame", nil, parent)
local sz = size or 4
s:SetPoint("TOPLEFT", parent, "TOPLEFT", -sz, sz)
s:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", sz, -sz)
s:SetFrameLevel(math.max(parent:GetFrameLevel() - 1, 0))
s:SetBackdrop({
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
tile = true, tileSize = 16, edgeSize = 16,
insets = { left = 4, right = 4, top = 4, bottom = 4 },
})
s:SetBackdropColor(0, 0, 0, 0.55)
s:SetBackdropBorderColor(0, 0, 0, 0.4)
return s
end
local function HideTexture(tex)
if not tex then return end
if tex.SetTexture then tex:SetTexture(nil) end
if tex.SetAlpha then tex:SetAlpha(0) end
if tex.Hide then tex:Hide() end
end
--------------------------------------------------------------------------------
-- Button Styling
--------------------------------------------------------------------------------
local MENU_BUTTON_ICONS = {
["GameMenuButtonContinue"] = "exit",
["GameMenuButtonUIOptions"] = "talent",
["GameMenuButtonKeybindings"] = "menu",
["GameMenuButtonRatings"] = "backpack",
["GameMenuButtonMacros"] = "ai",
["GameMenuButtonLogout"] = "close",
["GameMenuButtonQuit"] = "logout",
}
local function StyleMenuButton(btn)
if not btn or btn.nanamiStyled then return end
btn.nanamiStyled = true
HideTexture(btn:GetNormalTexture())
HideTexture(btn:GetPushedTexture())
HideTexture(btn:GetHighlightTexture())
HideTexture(btn:GetDisabledTexture())
local name = btn:GetName() or ""
for _, suffix in ipairs({ "Left", "Right", "Middle" }) do
local tex = _G[name .. suffix]
if tex then tex:SetAlpha(0); tex:Hide() end
end
SetRoundBackdrop(btn, T.btnBg, T.btnBorder)
btn:SetWidth(BUTTON_W)
btn:SetHeight(BUTTON_H)
local iconKey = MENU_BUTTON_ICONS[name]
local icoSize = 12
local gap = 4
local fs = btn:GetFontString()
if fs then
fs:SetFont(GetFont(), 11, "OUTLINE")
fs:SetTextColor(T.btnText[1], T.btnText[2], T.btnText[3])
fs:ClearAllPoints()
if iconKey and SFrames and SFrames.CreateIcon then
local ico = SFrames:CreateIcon(btn, iconKey, icoSize)
ico:SetDrawLayer("OVERLAY")
ico:SetVertexColor(T.btnText[1], T.btnText[2], T.btnText[3])
fs:SetPoint("CENTER", btn, "CENTER", (icoSize + gap) / 2, 0)
ico:SetPoint("RIGHT", fs, "LEFT", -gap, 0)
btn.nanamiIcon = ico
else
fs:SetPoint("CENTER", btn, "CENTER", 0, 0)
end
end
local origEnter = btn:GetScript("OnEnter")
local origLeave = btn:GetScript("OnLeave")
local origDown = btn:GetScript("OnMouseDown")
local origUp = btn:GetScript("OnMouseUp")
btn:SetScript("OnEnter", function()
if origEnter then origEnter() end
this:SetBackdropColor(T.btnHoverBg[1], T.btnHoverBg[2], T.btnHoverBg[3], T.btnHoverBg[4])
this:SetBackdropBorderColor(T.btnHoverBorder[1], T.btnHoverBorder[2], T.btnHoverBorder[3], T.btnHoverBorder[4])
local txt = this:GetFontString()
if txt then txt:SetTextColor(T.btnActiveText[1], T.btnActiveText[2], T.btnActiveText[3]) end
if this.nanamiIcon then this.nanamiIcon:SetVertexColor(T.btnActiveText[1], T.btnActiveText[2], T.btnActiveText[3]) end
end)
btn:SetScript("OnLeave", function()
if origLeave then origLeave() end
this:SetBackdropColor(T.btnBg[1], T.btnBg[2], T.btnBg[3], T.btnBg[4])
this:SetBackdropBorderColor(T.btnBorder[1], T.btnBorder[2], T.btnBorder[3], T.btnBorder[4])
local txt = this:GetFontString()
if txt then txt:SetTextColor(T.btnText[1], T.btnText[2], T.btnText[3]) end
if this.nanamiIcon then this.nanamiIcon:SetVertexColor(T.btnText[1], T.btnText[2], T.btnText[3]) end
end)
btn:SetScript("OnMouseDown", function()
if origDown then origDown() end
this:SetBackdropColor(T.btnDownBg[1], T.btnDownBg[2], T.btnDownBg[3], T.btnDownBg[4])
end)
btn:SetScript("OnMouseUp", function()
if origUp then origUp() end
this:SetBackdropColor(T.btnHoverBg[1], T.btnHoverBg[2], T.btnHoverBg[3], T.btnHoverBg[4])
end)
end
--------------------------------------------------------------------------------
-- Create Settings Button
--------------------------------------------------------------------------------
local settingsBtn
local function CreateSettingsButton(parent)
if settingsBtn then return settingsBtn end
local btn = CreateFrame("Button", "GameMenuButtonNanamiUI", parent)
btn:SetWidth(BUTTON_W)
btn:SetHeight(BUTTON_H)
SetRoundBackdrop(btn, T.btnBg, T.btnBorder)
local icoSize = 14
local gap = 4
local fs = btn:CreateFontString(nil, "OVERLAY")
fs:SetFont(GetFont(), 11, "OUTLINE")
fs:SetTextColor(T.btnText[1], T.btnText[2], T.btnText[3])
fs:SetPoint("CENTER", btn, "CENTER", (icoSize + gap) / 2, 0)
fs:SetText("Nanami-UI 设置")
local ico = SFrames:CreateIcon(btn, "logo", icoSize)
ico:SetDrawLayer("OVERLAY")
ico:SetVertexColor(T.btnText[1], T.btnText[2], T.btnText[3])
ico:SetPoint("RIGHT", fs, "LEFT", -gap, 0)
btn.nanamiIcon = ico
btn:SetScript("OnClick", function()
HideUIPanel(GameMenuFrame)
if SFrames.ConfigUI and SFrames.ConfigUI.Build then
SFrames.ConfigUI:Build("ui")
end
end)
btn:SetScript("OnEnter", function()
this:SetBackdropColor(T.btnHoverBg[1], T.btnHoverBg[2], T.btnHoverBg[3], T.btnHoverBg[4])
this:SetBackdropBorderColor(T.btnHoverBorder[1], T.btnHoverBorder[2], T.btnHoverBorder[3], T.btnHoverBorder[4])
fs:SetTextColor(T.btnActiveText[1], T.btnActiveText[2], T.btnActiveText[3])
ico:SetVertexColor(T.btnActiveText[1], T.btnActiveText[2], T.btnActiveText[3])
end)
btn:SetScript("OnLeave", function()
this:SetBackdropColor(T.btnBg[1], T.btnBg[2], T.btnBg[3], T.btnBg[4])
this:SetBackdropBorderColor(T.btnBorder[1], T.btnBorder[2], T.btnBorder[3], T.btnBorder[4])
fs:SetTextColor(T.btnText[1], T.btnText[2], T.btnText[3])
ico:SetVertexColor(T.btnText[1], T.btnText[2], T.btnText[3])
end)
btn:SetScript("OnMouseDown", function()
this:SetBackdropColor(T.btnDownBg[1], T.btnDownBg[2], T.btnDownBg[3], T.btnDownBg[4])
end)
btn:SetScript("OnMouseUp", function()
this:SetBackdropColor(T.btnHoverBg[1], T.btnHoverBg[2], T.btnHoverBg[3], T.btnHoverBg[4])
end)
btn.nanamiStyled = true
settingsBtn = btn
return btn
end
--------------------------------------------------------------------------------
-- Known button priority order (covers vanilla + Turtle WoW extras)
--------------------------------------------------------------------------------
local BUTTON_ORDER = {
"GameMenuButtonContinue",
"__NANAMI_SETTINGS__",
"GameMenuButtonUIOptions",
"GameMenuButtonKeybindings",
"GameMenuButtonRatings",
"GameMenuButtonMacros",
"GameMenuButtonLogout",
"GameMenuButtonQuit",
}
local HIDDEN_BUTTONS = {
"GameMenuButtonOptions",
"GameMenuButtonSoundOptions",
}
--------------------------------------------------------------------------------
-- Frame Styling (called once at PLAYER_LOGIN, before first show)
--------------------------------------------------------------------------------
local styled = false
local function StyleGameMenuFrame()
if styled then return end
if not GameMenuFrame then return end
styled = true
-- Hide all default background textures and header text
local regions = { GameMenuFrame:GetRegions() }
for _, region in ipairs(regions) do
if region then
local otype = region:GetObjectType()
if otype == "Texture" then
region:SetTexture(nil)
region:SetAlpha(0)
region:Hide()
elseif otype == "FontString" then
region:SetAlpha(0)
region:Hide()
end
end
end
SetRoundBackdrop(GameMenuFrame, T.panelBg, T.panelBorder)
CreateShadow(GameMenuFrame, 5)
-- Title
local title = GameMenuFrame:CreateFontString(nil, "OVERLAY")
title:SetFont(GetFont(), 13, "OUTLINE")
title:SetTextColor(T.titleColor[1], T.titleColor[2], T.titleColor[3])
title:SetPoint("TOP", GameMenuFrame, "TOP", 0, -11)
title:SetText("Nanami-UI")
-- Create settings button
local sBt = CreateSettingsButton(GameMenuFrame)
-- Hide removed buttons (Video / Sound)
for _, name in ipairs(HIDDEN_BUTTONS) do
local btn = _G[name]
if btn then
btn:Hide()
btn:SetWidth(0.001)
btn:SetHeight(0.001)
btn:ClearAllPoints()
btn:SetPoint("TOPLEFT", GameMenuFrame, "TOPLEFT", 0, 0)
end
end
-- Build a lookup of known names for quick check
local knownSet = {}
for _, name in ipairs(BUTTON_ORDER) do
if name ~= "__NANAMI_SETTINGS__" then
knownSet[name] = true
end
end
for _, name in ipairs(HIDDEN_BUTTONS) do
knownSet[name] = true
end
-- Collect all child buttons that are NOT the settings button
local children = { GameMenuFrame:GetChildren() }
local unknownBtns = {}
for _, child in ipairs(children) do
if child and child:GetObjectType() == "Button" and child ~= sBt then
local cname = child:GetName()
if cname and not knownSet[cname] then
table.insert(unknownBtns, child)
end
end
end
-- Build final ordered button list from BUTTON_ORDER
local orderedBtns = {}
for _, name in ipairs(BUTTON_ORDER) do
if name == "__NANAMI_SETTINGS__" then
table.insert(orderedBtns, sBt)
else
local btn = _G[name]
if btn then
StyleMenuButton(btn)
table.insert(orderedBtns, btn)
end
end
end
-- Append unknown / Turtle WoW extra buttons before Logout & Quit
local insertBefore = table.getn(orderedBtns)
for i = table.getn(orderedBtns), 1, -1 do
local bname = orderedBtns[i]:GetName() or ""
if bname == "GameMenuButtonLogout" or bname == "GameMenuButtonQuit" then
insertBefore = i
else
break
end
end
for _, btn in ipairs(unknownBtns) do
StyleMenuButton(btn)
table.insert(orderedBtns, insertBefore, btn)
insertBefore = insertBefore + 1
end
-- Layout vertically
local numBtns = table.getn(orderedBtns)
local totalH = numBtns * BUTTON_H + (numBtns - 1) * BUTTON_GAP
local frameH = HEADER_H + SIDE_PAD + totalH + SIDE_PAD
local frameW = BUTTON_W + SIDE_PAD * 2
GameMenuFrame:SetWidth(frameW)
GameMenuFrame:SetHeight(frameH)
local startY = -(HEADER_H + SIDE_PAD)
for i, btn in ipairs(orderedBtns) do
btn:ClearAllPoints()
btn:SetPoint("TOP", GameMenuFrame, "TOP", 0, startY - (i - 1) * (BUTTON_H + BUTTON_GAP))
end
end
--------------------------------------------------------------------------------
-- Hook: style at login, BEFORE any show (avoids OnShow size-change issues)
--------------------------------------------------------------------------------
local hookFrame = CreateFrame("Frame")
hookFrame:RegisterEvent("PLAYER_LOGIN")
hookFrame:SetScript("OnEvent", function()
if GameMenuFrame then
StyleGameMenuFrame()
end
end)