修复拾取界面点击无效问题 修复宠物训练界面不显示训练点问题 新增天赋分享到聊天界面 修复飞行界面无法关闭问题 修复术士宠物的显示问题 为天赋界面添加默认数据库支持 框架现在也可自主选择是否启用 玩家框架和目标框架可取消显示3D头像以及透明度修改 背包和银行也添加透明度自定义支持 优化tooltip性能和背包物品显示方式 修复布局模式在ui缩放后不能正常定位的问题 添加硬核模式危险和死亡的工会通报 添加拾取和已拾取的框体 等等
780 lines
26 KiB
Lua
780 lines
26 KiB
Lua
--------------------------------------------------------------------------------
|
||
-- Nanami-UI: Minimap Skin (Minimap.lua)
|
||
-- Custom cat-paw pixel art frame for the minimap
|
||
--------------------------------------------------------------------------------
|
||
|
||
SFrames.Minimap = SFrames.Minimap or {}
|
||
local MM = SFrames.Minimap
|
||
local _A = SFrames.ActiveTheme
|
||
|
||
local MAP_STYLES = {
|
||
{ key = "map", tex = "Interface\\AddOns\\Nanami-UI\\img\\map", label = "猫爪", plateY = -10, textColor = {0.45, 0.32, 0.20} },
|
||
{ key = "zs", tex = "Interface\\AddOns\\Nanami-UI\\img\\zs", label = "战士", plateY = -6, textColor = {1, 1, 1} },
|
||
{ key = "qs", tex = "Interface\\AddOns\\Nanami-UI\\img\\qs", label = "圣骑士", plateY = -6, textColor = {0.22, 0.13, 0.07} },
|
||
{ key = "lr", tex = "Interface\\AddOns\\Nanami-UI\\img\\lr", label = "猎人", plateY = -6, textColor = {1, 1, 1} },
|
||
{ key = "qxz", tex = "Interface\\AddOns\\Nanami-UI\\img\\qxz", label = "潜行者", plateY = -6, textColor = {1, 1, 1} },
|
||
{ key = "ms", tex = "Interface\\AddOns\\Nanami-UI\\img\\ms", label = "牧师", plateY = -6, textColor = {0.22, 0.13, 0.07} },
|
||
{ key = "sm", tex = "Interface\\AddOns\\Nanami-UI\\img\\sm", label = "萨满", plateY = -6, textColor = {1, 1, 1} },
|
||
{ key = "fs", tex = "Interface\\AddOns\\Nanami-UI\\img\\fs", label = "法师", plateY = -6, textColor = {1, 1, 1} },
|
||
{ key = "ss", tex = "Interface\\AddOns\\Nanami-UI\\img\\ss", label = "术士", plateY = -6, textColor = {1, 1, 1} },
|
||
{ key = "dly", tex = "Interface\\AddOns\\Nanami-UI\\img\\dly", label = "德鲁伊", plateY = -6, textColor = {0.22, 0.13, 0.07} },
|
||
}
|
||
local SQUARE_STYLES = {
|
||
{
|
||
key = "square1",
|
||
label = "方形·金",
|
||
tex = "Interface\\AddOns\\Nanami-UI\\img\\map_f_1",
|
||
texSize = 512,
|
||
mapX = 9, mapY = 9, mapW = 486, mapH = 486,
|
||
zoneOverlay = true,
|
||
textColor = {0.85, 0.75, 0.55},
|
||
},
|
||
{
|
||
key = "square2",
|
||
label = "方形·暗",
|
||
tex = "Interface\\AddOns\\Nanami-UI\\img\\map_f_2",
|
||
texSize = 512,
|
||
mapX = 52, mapY = 61, mapW = 418, mapH = 418,
|
||
zonePlateX = 104, zonePlateY = 18, zonePlateW = 302, zonePlateH = 45,
|
||
textColor = {0.8, 0.8, 0.8},
|
||
},
|
||
}
|
||
local SQUARE_MASK = "Interface\\BUTTONS\\WHITE8X8"
|
||
|
||
local TEX_SIZE = 512
|
||
local CIRCLE_CX = 256
|
||
local CIRCLE_CY = 256
|
||
local CIRCLE_R = 210
|
||
local PLATE_X = 103
|
||
local PLATE_Y = 29
|
||
local PLATE_W = 200
|
||
local PLATE_H = 66
|
||
local BASE_SIZE = 180
|
||
|
||
local CLASS_STYLE_MAP = {
|
||
["Warrior"] = "zs", ["WARRIOR"] = "zs", ["战士"] = "zs",
|
||
["Paladin"] = "qs", ["PALADIN"] = "qs", ["圣骑士"] = "qs",
|
||
["Hunter"] = "lr", ["HUNTER"] = "lr", ["猎人"] = "lr",
|
||
["Rogue"] = "qxz", ["ROGUE"] = "qxz", ["潜行者"] = "qxz",
|
||
["Priest"] = "ms", ["PRIEST"] = "ms", ["牧师"] = "ms",
|
||
["Shaman"] = "sm", ["SHAMAN"] = "sm", ["萨满祭司"] = "sm",
|
||
["Mage"] = "fs", ["MAGE"] = "fs", ["法师"] = "fs",
|
||
["Warlock"] = "ss", ["WARLOCK"] = "ss", ["术士"] = "ss",
|
||
["Druid"] = "dly", ["DRUID"] = "dly", ["德鲁伊"] = "dly",
|
||
}
|
||
|
||
local DEFAULTS = {
|
||
enabled = true,
|
||
scale = 1.0,
|
||
showClock = true,
|
||
showCoords = true,
|
||
mapStyle = "auto",
|
||
mapShape = "square1",
|
||
posX = -5,
|
||
posY = -5,
|
||
mailIconX = nil,
|
||
mailIconY = nil,
|
||
}
|
||
|
||
local container, overlayFrame, overlayTex
|
||
local zoneFs, clockFs, clockBg, coordFs, zoneBg
|
||
local built = false
|
||
|
||
--------------------------------------------------------------------------------
|
||
-- Helpers
|
||
--------------------------------------------------------------------------------
|
||
local function GetDB()
|
||
if not SFramesDB then SFramesDB = {} end
|
||
if type(SFramesDB.Minimap) ~= "table" then SFramesDB.Minimap = {} end
|
||
local db = SFramesDB.Minimap
|
||
for k, v in pairs(DEFAULTS) do
|
||
if db[k] == nil then db[k] = v end
|
||
end
|
||
return db
|
||
end
|
||
|
||
local function ResolveStyleKey()
|
||
local key = GetDB().mapStyle or "auto"
|
||
if key == "auto" then
|
||
local localName, engName = UnitClass("player")
|
||
key = CLASS_STYLE_MAP[engName]
|
||
or CLASS_STYLE_MAP[localName]
|
||
or "map"
|
||
end
|
||
return key
|
||
end
|
||
|
||
local function GetCurrentStyle()
|
||
local key = ResolveStyleKey()
|
||
for _, s in ipairs(MAP_STYLES) do
|
||
if s.key == key then return s end
|
||
end
|
||
return MAP_STYLES[1]
|
||
end
|
||
|
||
local function GetMapTexture()
|
||
return GetCurrentStyle().tex
|
||
end
|
||
|
||
local function IsSquareShape()
|
||
local shape = GetDB().mapShape or "square1"
|
||
return shape == "square1" or shape == "square2"
|
||
end
|
||
|
||
local function GetSquareStyle()
|
||
local shape = GetDB().mapShape or "square1"
|
||
for _, s in ipairs(SQUARE_STYLES) do
|
||
if s.key == shape then return s end
|
||
end
|
||
return SQUARE_STYLES[1]
|
||
end
|
||
|
||
local function S(texPx, frameSize)
|
||
return texPx / TEX_SIZE * frameSize
|
||
end
|
||
|
||
local function FrameSize()
|
||
return math.floor(BASE_SIZE * ((GetDB().scale) or 1))
|
||
end
|
||
|
||
local function ApplyPosition()
|
||
if not container then return end
|
||
local pos = SFramesDB and SFramesDB.Positions and SFramesDB.Positions["Minimap"]
|
||
if pos and pos.point and pos.relativePoint then
|
||
container:ClearAllPoints()
|
||
container:SetPoint(pos.point, UIParent, pos.relativePoint, pos.xOfs or 0, pos.yOfs or 0)
|
||
else
|
||
local db = GetDB()
|
||
local x = tonumber(db.posX) or -5
|
||
local y = tonumber(db.posY) or -5
|
||
container:ClearAllPoints()
|
||
container:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT", x, y)
|
||
end
|
||
end
|
||
|
||
--------------------------------------------------------------------------------
|
||
-- Hide default Blizzard minimap chrome
|
||
-- MUST be called AFTER BuildFrame (Minimap is already reparented)
|
||
--------------------------------------------------------------------------------
|
||
local function HideDefaultElements()
|
||
local kill = {
|
||
MinimapBorder,
|
||
MinimapBorderTop,
|
||
MinimapZoomIn,
|
||
MinimapZoomOut,
|
||
MinimapToggleButton,
|
||
MiniMapWorldMapButton,
|
||
GameTimeFrame,
|
||
MinimapZoneTextButton,
|
||
MiniMapTracking,
|
||
MinimapBackdrop,
|
||
}
|
||
for _, f in ipairs(kill) do
|
||
if f then
|
||
f:Hide()
|
||
f.Show = function() end
|
||
end
|
||
end
|
||
|
||
-- Hide all tracking-related frames (Turtle WoW dual tracking, etc.)
|
||
local trackNames = {
|
||
"MiniMapTrackingButton", "MiniMapTrackingFrame",
|
||
"MiniMapTrackingIcon", "MiniMapTracking1", "MiniMapTracking2",
|
||
}
|
||
for _, name in ipairs(trackNames) do
|
||
local f = _G[name]
|
||
if f and f.Hide then
|
||
f:Hide()
|
||
f.Show = function() end
|
||
end
|
||
end
|
||
|
||
-- Also hide any tracking textures that are children of Minimap
|
||
if Minimap.GetChildren then
|
||
local children = { Minimap:GetChildren() }
|
||
for _, child in ipairs(children) do
|
||
local n = child.GetName and child:GetName()
|
||
if n and string.find(n, "Track") then
|
||
child:Hide()
|
||
child.Show = function() end
|
||
end
|
||
end
|
||
end
|
||
|
||
-- Move MinimapCluster off-screen instead of Hide()
|
||
-- Hide() would cascade-hide children that were still parented at load time
|
||
if MinimapCluster then
|
||
MinimapCluster:ClearAllPoints()
|
||
MinimapCluster:SetPoint("TOP", UIParent, "BOTTOM", 0, -500)
|
||
MinimapCluster:SetWidth(1)
|
||
MinimapCluster:SetHeight(1)
|
||
MinimapCluster:EnableMouse(false)
|
||
end
|
||
end
|
||
|
||
--------------------------------------------------------------------------------
|
||
-- Build
|
||
--------------------------------------------------------------------------------
|
||
local function BuildFrame()
|
||
if built then return end
|
||
built = true
|
||
|
||
local fs = FrameSize()
|
||
local isSquare = IsSquareShape()
|
||
|
||
-- Main container
|
||
container = CreateFrame("Frame", "SFramesMinimapContainer", UIParent)
|
||
container:SetWidth(fs)
|
||
container:SetHeight(fs)
|
||
container:SetFrameStrata("LOW")
|
||
container:SetFrameLevel(1)
|
||
container:EnableMouse(false)
|
||
container:SetClampedToScreen(true)
|
||
|
||
-- Reparent the actual minimap into our container
|
||
Minimap:SetParent(container)
|
||
Minimap:ClearAllPoints()
|
||
if isSquare then
|
||
local sq = GetSquareStyle()
|
||
local mapW = sq.mapW / sq.texSize * fs
|
||
local mapH = sq.mapH / sq.texSize * fs
|
||
local cx = (sq.mapX + sq.mapW / 2) / sq.texSize * fs
|
||
local cy = (sq.mapY + sq.mapH / 2) / sq.texSize * fs
|
||
Minimap:SetPoint("CENTER", container, "TOPLEFT", cx, -cy)
|
||
Minimap:SetWidth(mapW)
|
||
Minimap:SetHeight(mapH)
|
||
else
|
||
local mapDiam = math.floor(S((CIRCLE_R + 8) * 2, fs))
|
||
Minimap:SetPoint("CENTER", container, "TOPLEFT",
|
||
S(CIRCLE_CX, fs), -S(CIRCLE_CY, fs))
|
||
Minimap:SetWidth(mapDiam)
|
||
Minimap:SetHeight(mapDiam)
|
||
end
|
||
Minimap:SetFrameStrata("LOW")
|
||
Minimap:SetFrameLevel(2)
|
||
Minimap:Show()
|
||
|
||
if Minimap.SetMaskTexture then
|
||
if isSquare then
|
||
Minimap:SetMaskTexture(SQUARE_MASK)
|
||
else
|
||
Minimap:SetMaskTexture("Textures\\MinimapMask")
|
||
end
|
||
end
|
||
|
||
-- Decorative overlay (frame texture)
|
||
overlayFrame = CreateFrame("Frame", nil, container)
|
||
overlayFrame:SetAllPoints(container)
|
||
overlayFrame:SetFrameStrata("LOW")
|
||
overlayFrame:SetFrameLevel(Minimap:GetFrameLevel() + 3)
|
||
overlayFrame:EnableMouse(false)
|
||
|
||
overlayTex = overlayFrame:CreateTexture(nil, "ARTWORK")
|
||
if isSquare then
|
||
overlayTex:SetTexture(GetSquareStyle().tex)
|
||
else
|
||
overlayTex:SetTexture(GetMapTexture())
|
||
end
|
||
overlayTex:SetAllPoints(overlayFrame)
|
||
|
||
-- Zone name background (semi-transparent strip for square styles)
|
||
zoneBg = CreateFrame("Frame", nil, overlayFrame)
|
||
zoneBg:SetFrameLevel(overlayFrame:GetFrameLevel() - 1)
|
||
zoneBg:SetBackdrop({
|
||
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
||
})
|
||
zoneBg:SetBackdropColor(0, 0, 0, 0.5)
|
||
zoneBg:Hide()
|
||
|
||
-- Zone name
|
||
zoneFs = overlayFrame:CreateFontString(nil, "OVERLAY")
|
||
zoneFs:SetJustifyH("CENTER")
|
||
zoneFs:SetJustifyV("MIDDLE")
|
||
|
||
if isSquare then
|
||
local sq = GetSquareStyle()
|
||
zoneFs:SetFont(SFrames:GetFont(), 11, "OUTLINE")
|
||
if sq.zonePlateX then
|
||
local px = (sq.zonePlateX + sq.zonePlateW / 2) / sq.texSize * fs
|
||
local py = (sq.zonePlateY + sq.zonePlateH / 2) / sq.texSize * fs
|
||
zoneFs:SetPoint("CENTER", container, "TOPLEFT", px, -py)
|
||
zoneFs:SetWidth(sq.zonePlateW / sq.texSize * fs)
|
||
zoneFs:SetHeight(sq.zonePlateH / sq.texSize * fs)
|
||
else
|
||
zoneFs:SetPoint("TOP", Minimap, "TOP", 0, -3)
|
||
zoneFs:SetWidth(Minimap:GetWidth() * 0.7)
|
||
zoneFs:SetHeight(18)
|
||
zoneBg:ClearAllPoints()
|
||
zoneBg:SetPoint("TOP", Minimap, "TOP", 0, 0)
|
||
zoneBg:SetWidth(Minimap:GetWidth())
|
||
zoneBg:SetHeight(20)
|
||
zoneBg:Show()
|
||
end
|
||
local tc = sq.textColor or {1, 1, 1}
|
||
zoneFs:SetTextColor(tc[1], tc[2], tc[3])
|
||
else
|
||
local style = GetCurrentStyle()
|
||
zoneFs:SetFont(SFrames:GetFont(), 11, "")
|
||
local pcy = S(PLATE_Y + PLATE_H / 2 + (style.plateY or -6), fs)
|
||
zoneFs:SetPoint("CENTER", container, "TOP", 0, -pcy)
|
||
zoneFs:SetWidth(S(PLATE_W + 60, fs))
|
||
zoneFs:SetHeight(S(PLATE_H, fs))
|
||
local tc = style.textColor or {0.22, 0.13, 0.07}
|
||
zoneFs:SetTextColor(tc[1], tc[2], tc[3])
|
||
end
|
||
|
||
-- Clock background (semi-transparent rounded)
|
||
clockBg = CreateFrame("Frame", nil, overlayFrame)
|
||
clockBg:SetFrameLevel(overlayFrame:GetFrameLevel() + 1)
|
||
clockBg:SetBackdrop({
|
||
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
||
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
|
||
tile = true, tileSize = 16, edgeSize = 10,
|
||
insets = { left = 2, right = 2, top = 2, bottom = 2 },
|
||
})
|
||
local _clkBg = _A.clockBg or { 0, 0, 0, 0.55 }
|
||
local _clkBd = _A.clockBorder or { 0, 0, 0, 0.3 }
|
||
clockBg:SetBackdropColor(_clkBg[1], _clkBg[2], _clkBg[3], _clkBg[4])
|
||
clockBg:SetBackdropBorderColor(_clkBd[1], _clkBd[2], _clkBd[3], _clkBd[4])
|
||
clockBg:SetWidth(46)
|
||
clockBg:SetHeight(18)
|
||
if isSquare then
|
||
clockBg:SetPoint("TOP", Minimap, "BOTTOM", 0, -2)
|
||
else
|
||
clockBg:SetPoint("CENTER", container, "BOTTOM", 0,
|
||
S((TEX_SIZE - CIRCLE_CY - CIRCLE_R) / 2, fs))
|
||
end
|
||
|
||
-- Clock text
|
||
clockFs = clockBg:CreateFontString(nil, "OVERLAY")
|
||
clockFs:SetFont(SFrames:GetFont(), 10, "OUTLINE")
|
||
clockFs:SetPoint("CENTER", clockBg, "CENTER", 0, 0)
|
||
clockFs:SetJustifyH("CENTER")
|
||
local _clkTxt = _A.clockText or { 0.92, 0.84, 0.72 }
|
||
clockFs:SetTextColor(_clkTxt[1], _clkTxt[2], _clkTxt[3])
|
||
|
||
-- Coordinates (inside map area, near bottom)
|
||
coordFs = overlayFrame:CreateFontString(nil, "OVERLAY")
|
||
coordFs:SetFont(SFrames:GetFont(), 9, "OUTLINE")
|
||
coordFs:SetPoint("BOTTOM", Minimap, "BOTTOM", 0, 8)
|
||
coordFs:SetJustifyH("CENTER")
|
||
local _coordTxt = _A.coordText or { 0.80, 0.80, 0.80 }
|
||
coordFs:SetTextColor(_coordTxt[1], _coordTxt[2], _coordTxt[3])
|
||
|
||
MM.container = container
|
||
MM.overlayFrame = overlayFrame
|
||
end
|
||
|
||
--------------------------------------------------------------------------------
|
||
-- Interactions
|
||
--------------------------------------------------------------------------------
|
||
local function SetupScrollZoom()
|
||
Minimap:EnableMouseWheel(true)
|
||
Minimap:SetScript("OnMouseWheel", function()
|
||
if arg1 > 0 then
|
||
Minimap_ZoomIn()
|
||
else
|
||
Minimap_ZoomOut()
|
||
end
|
||
end)
|
||
end
|
||
|
||
local function SetupMouseHandler()
|
||
Minimap:SetScript("OnMouseUp", function()
|
||
if arg1 == "RightButton" then
|
||
if MiniMapTrackingDropDown then
|
||
ToggleDropDownMenu(1, nil, MiniMapTrackingDropDown, "cursor")
|
||
end
|
||
else
|
||
if Minimap_OnClick then
|
||
Minimap_OnClick(this)
|
||
end
|
||
end
|
||
end)
|
||
end
|
||
|
||
MM.ApplyPosition = ApplyPosition
|
||
|
||
--------------------------------------------------------------------------------
|
||
-- Reposition child icons
|
||
--------------------------------------------------------------------------------
|
||
local function SetupMailDragging()
|
||
if not MiniMapMailFrame then return end
|
||
|
||
MiniMapMailFrame:SetMovable(true)
|
||
MiniMapMailFrame:EnableMouse(true)
|
||
MiniMapMailFrame:RegisterForDrag("LeftButton")
|
||
|
||
MiniMapMailFrame:SetScript("OnDragStart", function()
|
||
MiniMapMailFrame:StartMoving()
|
||
end)
|
||
|
||
MiniMapMailFrame:SetScript("OnDragStop", function()
|
||
MiniMapMailFrame:StopMovingOrSizing()
|
||
local db = GetDB()
|
||
local cx, cy = MiniMapMailFrame:GetCenter()
|
||
local ux, uy = UIParent:GetCenter()
|
||
if cx and cy and ux and uy then
|
||
db.mailIconX = cx - ux
|
||
db.mailIconY = cy - uy
|
||
end
|
||
end)
|
||
end
|
||
|
||
local function RepositionIcons()
|
||
if MiniMapMailFrame then
|
||
local db = GetDB()
|
||
MiniMapMailFrame:ClearAllPoints()
|
||
if db.mailIconX and db.mailIconY then
|
||
MiniMapMailFrame:SetPoint("CENTER", UIParent, "CENTER", db.mailIconX, db.mailIconY)
|
||
else
|
||
local mapDiam = Minimap:GetWidth()
|
||
MiniMapMailFrame:SetPoint("RIGHT", Minimap, "RIGHT", 8, mapDiam * 0.12)
|
||
end
|
||
MiniMapMailFrame:SetFrameStrata("LOW")
|
||
MiniMapMailFrame:SetFrameLevel((overlayFrame and overlayFrame:GetFrameLevel() or 5) + 2)
|
||
SetupMailDragging()
|
||
end
|
||
|
||
if MiniMapBattlefieldFrame then
|
||
MiniMapBattlefieldFrame:ClearAllPoints()
|
||
MiniMapBattlefieldFrame:SetPoint("BOTTOMLEFT", Minimap, "BOTTOM", 15, -8)
|
||
MiniMapBattlefieldFrame:SetFrameStrata("LOW")
|
||
MiniMapBattlefieldFrame:SetFrameLevel((overlayFrame and overlayFrame:GetFrameLevel() or 5) + 2)
|
||
end
|
||
end
|
||
|
||
--------------------------------------------------------------------------------
|
||
-- Update helpers
|
||
--------------------------------------------------------------------------------
|
||
local function UpdateZoneText()
|
||
if not zoneFs then return end
|
||
local text = GetMinimapZoneText and GetMinimapZoneText() or ""
|
||
lastZoneText = text
|
||
zoneFs:SetText(text)
|
||
end
|
||
|
||
local function SetZoneMap()
|
||
if SetMapToCurrentZone then
|
||
pcall(SetMapToCurrentZone)
|
||
end
|
||
end
|
||
|
||
local clockTimer = 0
|
||
local coordTimer = 0
|
||
local zoneTimer = 0
|
||
local lastZoneText = ""
|
||
|
||
local function OnUpdate()
|
||
local dt = arg1 or 0
|
||
local db = GetDB()
|
||
|
||
-- Clock (every 1 s)
|
||
clockTimer = clockTimer + dt
|
||
if clockTimer >= 1 then
|
||
clockTimer = 0
|
||
if db.showClock and clockFs then
|
||
local timeStr
|
||
if date then
|
||
timeStr = date("%H:%M")
|
||
else
|
||
local h, m = GetGameTime()
|
||
timeStr = string.format("%02d:%02d", h, m)
|
||
end
|
||
clockFs:SetText(timeStr)
|
||
clockFs:Show()
|
||
if clockBg then clockBg:Show() end
|
||
elseif clockFs then
|
||
clockFs:Hide()
|
||
if clockBg then clockBg:Hide() end
|
||
end
|
||
end
|
||
|
||
-- Zone text (every 1 s) – catches late API updates missed by events
|
||
zoneTimer = zoneTimer + dt
|
||
if zoneTimer >= 1 then
|
||
zoneTimer = 0
|
||
if zoneFs and GetMinimapZoneText then
|
||
local cur = GetMinimapZoneText() or ""
|
||
if cur ~= lastZoneText then
|
||
lastZoneText = cur
|
||
zoneFs:SetText(cur)
|
||
end
|
||
end
|
||
end
|
||
|
||
-- Coordinates (every 0.25 s)
|
||
coordTimer = coordTimer + dt
|
||
if coordTimer >= 0.25 then
|
||
coordTimer = 0
|
||
if db.showCoords and coordFs and GetPlayerMapPosition then
|
||
local ok, x, y = pcall(GetPlayerMapPosition, "player")
|
||
if ok and x and y and (x > 0 or y > 0) then
|
||
coordFs:SetText(string.format("%.1f, %.1f", x * 100, y * 100))
|
||
coordFs:Show()
|
||
else
|
||
coordFs:Hide()
|
||
end
|
||
elseif coordFs then
|
||
coordFs:Hide()
|
||
end
|
||
end
|
||
end
|
||
|
||
--------------------------------------------------------------------------------
|
||
-- Public API
|
||
--------------------------------------------------------------------------------
|
||
function MM:Refresh()
|
||
if not container then return end
|
||
|
||
local fs = FrameSize()
|
||
local isSquare = IsSquareShape()
|
||
|
||
container:SetWidth(fs)
|
||
container:SetHeight(fs)
|
||
|
||
-- Apply mask
|
||
if Minimap.SetMaskTexture then
|
||
if isSquare then
|
||
Minimap:SetMaskTexture(SQUARE_MASK)
|
||
else
|
||
Minimap:SetMaskTexture("Textures\\MinimapMask")
|
||
end
|
||
end
|
||
|
||
-- Position and size minimap
|
||
Minimap:ClearAllPoints()
|
||
if isSquare then
|
||
local sq = GetSquareStyle()
|
||
local mapW = sq.mapW / sq.texSize * fs
|
||
local mapH = sq.mapH / sq.texSize * fs
|
||
local cx = (sq.mapX + sq.mapW / 2) / sq.texSize * fs
|
||
local cy = (sq.mapY + sq.mapH / 2) / sq.texSize * fs
|
||
Minimap:SetPoint("CENTER", container, "TOPLEFT", cx, -cy)
|
||
Minimap:SetWidth(mapW)
|
||
Minimap:SetHeight(mapH)
|
||
else
|
||
local mapDiam = math.floor(S((CIRCLE_R + 8) * 2, fs))
|
||
Minimap:SetPoint("CENTER", container, "TOPLEFT",
|
||
S(CIRCLE_CX, fs), -S(CIRCLE_CY, fs))
|
||
Minimap:SetWidth(mapDiam)
|
||
Minimap:SetHeight(mapDiam)
|
||
end
|
||
|
||
-- Update overlay texture
|
||
if overlayTex then
|
||
if isSquare then
|
||
overlayTex:SetTexture(GetSquareStyle().tex)
|
||
else
|
||
overlayTex:SetTexture(GetMapTexture())
|
||
end
|
||
end
|
||
|
||
-- Update zone text
|
||
if zoneFs then
|
||
zoneFs:ClearAllPoints()
|
||
if isSquare then
|
||
local sq = GetSquareStyle()
|
||
zoneFs:SetFont(SFrames:GetFont(), 11, "OUTLINE")
|
||
if sq.zonePlateX then
|
||
local px = (sq.zonePlateX + sq.zonePlateW / 2) / sq.texSize * fs
|
||
local py = (sq.zonePlateY + sq.zonePlateH / 2) / sq.texSize * fs
|
||
zoneFs:SetPoint("CENTER", container, "TOPLEFT", px, -py)
|
||
zoneFs:SetWidth(sq.zonePlateW / sq.texSize * fs)
|
||
zoneFs:SetHeight(sq.zonePlateH / sq.texSize * fs)
|
||
else
|
||
zoneFs:SetPoint("TOP", Minimap, "TOP", 0, -3)
|
||
zoneFs:SetWidth(Minimap:GetWidth() * 0.7)
|
||
zoneFs:SetHeight(18)
|
||
end
|
||
local tc = sq.textColor or {1, 1, 1}
|
||
zoneFs:SetTextColor(tc[1], tc[2], tc[3])
|
||
else
|
||
zoneFs:SetFont(SFrames:GetFont(), 11, "")
|
||
local style = GetCurrentStyle()
|
||
local pcy = S(PLATE_Y + PLATE_H / 2 + (style.plateY or -6), fs)
|
||
zoneFs:SetPoint("CENTER", container, "TOP", 0, -pcy)
|
||
zoneFs:SetWidth(S(PLATE_W + 60, fs))
|
||
local tc = style.textColor or {0.22, 0.13, 0.07}
|
||
zoneFs:SetTextColor(tc[1], tc[2], tc[3])
|
||
end
|
||
end
|
||
|
||
-- Zone background (semi-transparent strip, only for square styles with zoneOverlay)
|
||
if zoneBg then
|
||
if isSquare and GetSquareStyle().zoneOverlay then
|
||
zoneBg:ClearAllPoints()
|
||
zoneBg:SetPoint("TOP", Minimap, "TOP", 0, 0)
|
||
zoneBg:SetWidth(Minimap:GetWidth())
|
||
zoneBg:SetHeight(20)
|
||
zoneBg:Show()
|
||
else
|
||
zoneBg:Hide()
|
||
end
|
||
end
|
||
|
||
-- Clock
|
||
if clockBg then
|
||
clockBg:ClearAllPoints()
|
||
if isSquare then
|
||
clockBg:SetPoint("TOP", Minimap, "BOTTOM", 0, -2)
|
||
else
|
||
clockBg:SetPoint("CENTER", container, "BOTTOM", 0,
|
||
S((TEX_SIZE - CIRCLE_CY - CIRCLE_R) / 2, fs))
|
||
end
|
||
end
|
||
|
||
-- Coords
|
||
if coordFs then
|
||
coordFs:ClearAllPoints()
|
||
coordFs:SetPoint("BOTTOM", Minimap, "BOTTOM", 0, 8)
|
||
end
|
||
|
||
UpdateZoneText()
|
||
RepositionIcons()
|
||
end
|
||
|
||
MM.MAP_STYLES = MAP_STYLES
|
||
MM.SQUARE_STYLES = SQUARE_STYLES
|
||
|
||
--------------------------------------------------------------------------------
|
||
-- Shield: re-apply our skin after other addons (ShaguTweaks etc.) touch Minimap
|
||
--------------------------------------------------------------------------------
|
||
local shielded = false
|
||
|
||
local function ShieldMinimap()
|
||
if shielded then return end
|
||
shielded = true
|
||
|
||
if Minimap:GetParent() ~= container then
|
||
Minimap:SetParent(container)
|
||
end
|
||
|
||
local fs = FrameSize()
|
||
local isSquare = IsSquareShape()
|
||
|
||
Minimap:ClearAllPoints()
|
||
if isSquare then
|
||
local sq = GetSquareStyle()
|
||
local mapW = sq.mapW / sq.texSize * fs
|
||
local mapH = sq.mapH / sq.texSize * fs
|
||
local cx = (sq.mapX + sq.mapW / 2) / sq.texSize * fs
|
||
local cy = (sq.mapY + sq.mapH / 2) / sq.texSize * fs
|
||
Minimap:SetPoint("CENTER", container, "TOPLEFT", cx, -cy)
|
||
Minimap:SetWidth(mapW)
|
||
Minimap:SetHeight(mapH)
|
||
else
|
||
local mapDiam = math.floor(S((CIRCLE_R + 8) * 2, fs))
|
||
Minimap:SetPoint("CENTER", container, "TOPLEFT",
|
||
S(CIRCLE_CX, fs), -S(CIRCLE_CY, fs))
|
||
Minimap:SetWidth(mapDiam)
|
||
Minimap:SetHeight(mapDiam)
|
||
end
|
||
Minimap:SetFrameStrata("LOW")
|
||
Minimap:SetFrameLevel(2)
|
||
Minimap:Show()
|
||
|
||
if Minimap.SetMaskTexture then
|
||
if isSquare then
|
||
Minimap:SetMaskTexture(SQUARE_MASK)
|
||
else
|
||
Minimap:SetMaskTexture("Textures\\MinimapMask")
|
||
end
|
||
end
|
||
|
||
HideDefaultElements()
|
||
|
||
-- Kill any border/backdrop that ShaguTweaks may have injected
|
||
local regions = { Minimap:GetRegions() }
|
||
for _, r in ipairs(regions) do
|
||
if r and r:IsObjectType("Texture") then
|
||
local tex = r.GetTexture and r:GetTexture()
|
||
if tex and type(tex) == "string" then
|
||
local low = string.lower(tex)
|
||
if string.find(low, "border") or string.find(low, "backdrop")
|
||
or string.find(low, "overlay") or string.find(low, "background") then
|
||
r:Hide()
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
shielded = false
|
||
end
|
||
|
||
function MM:Initialize()
|
||
if not Minimap then return end
|
||
|
||
local db = GetDB()
|
||
if db.enabled == false then return end
|
||
|
||
local ok, err = pcall(function()
|
||
-- Build first (reparents Minimap), THEN hide old chrome
|
||
BuildFrame()
|
||
HideDefaultElements()
|
||
|
||
-- Ensure Minimap is visible after reparent
|
||
Minimap:Show()
|
||
|
||
SetupScrollZoom()
|
||
SetupMouseHandler()
|
||
|
||
-- Apply position from settings
|
||
ApplyPosition()
|
||
|
||
RepositionIcons()
|
||
|
||
-- Zone text events
|
||
SFrames:RegisterEvent("ZONE_CHANGED", function()
|
||
SetZoneMap()
|
||
UpdateZoneText()
|
||
end)
|
||
SFrames:RegisterEvent("ZONE_CHANGED_NEW_AREA", function()
|
||
SetZoneMap()
|
||
UpdateZoneText()
|
||
end)
|
||
SFrames:RegisterEvent("ZONE_CHANGED_INDOORS", function()
|
||
SetZoneMap()
|
||
UpdateZoneText()
|
||
end)
|
||
|
||
-- Re-apply after other addons finish loading (ShaguTweaks etc.)
|
||
SFrames:RegisterEvent("PLAYER_ENTERING_WORLD", function()
|
||
pcall(ShieldMinimap)
|
||
pcall(UpdateZoneText)
|
||
end)
|
||
|
||
-- Delayed zone text: GetMinimapZoneText() may be empty at PLAYER_LOGIN
|
||
local zoneDelay = CreateFrame("Frame")
|
||
local elapsed = 0
|
||
zoneDelay:SetScript("OnUpdate", function()
|
||
elapsed = elapsed + (arg1 or 0)
|
||
if elapsed >= 1 then
|
||
zoneDelay:SetScript("OnUpdate", nil)
|
||
pcall(SetZoneMap)
|
||
pcall(UpdateZoneText)
|
||
end
|
||
end)
|
||
|
||
-- Tick
|
||
container:SetScript("OnUpdate", OnUpdate)
|
||
|
||
-- First refresh
|
||
SetZoneMap()
|
||
UpdateZoneText()
|
||
MM:Refresh()
|
||
end)
|
||
|
||
if not ok then
|
||
DEFAULT_CHAT_FRAME:AddMessage("|cffff4444Nanami-UI Minimap error: " .. tostring(err) .. "|r")
|
||
end
|
||
|
||
if SFrames.Movers and SFrames.Movers.RegisterMover and container then
|
||
SFrames.Movers:RegisterMover("Minimap", container, "小地图",
|
||
"TOPRIGHT", "UIParent", "TOPRIGHT", db.posX or -5, db.posY or -5,
|
||
function()
|
||
pcall(RepositionIcons)
|
||
end)
|
||
end
|
||
end
|