Files
Nanami-UI/Minimap.lua
2026-04-09 09:46:47 +08:00

822 lines
27 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.

--------------------------------------------------------------------------------
-- 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 IsMapStateProtected()
if WorldMapFrame and WorldMapFrame:IsVisible() then
return true
end
if BattlefieldMinimap and BattlefieldMinimap:IsVisible() then
return true
end
if BattlefieldMinimapFrame and BattlefieldMinimapFrame:IsVisible() then
return true
end
return false
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
local function HideTooltipIfOwned(frame)
if not frame or not GameTooltip or not GameTooltip:IsVisible() then
return
end
if GameTooltip.IsOwned and GameTooltip:IsOwned(frame) then
GameTooltip:Hide()
return
end
if GameTooltip.GetOwner and GameTooltip:GetOwner() == frame then
GameTooltip:Hide()
end
end
local function ForceHideMinimapFrame(frame)
if not frame then return end
HideTooltipIfOwned(frame)
if frame.EnableMouse then
frame:EnableMouse(false)
end
if frame.Hide then
frame:Hide()
end
if frame.SetAlpha then
frame:SetAlpha(0)
end
frame.Show = function() 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,
TimeManagerClockButton,
MinimapZoneTextButton,
MiniMapTracking,
MinimapBackdrop,
}
for _, f in ipairs(kill) do
ForceHideMinimapFrame(f)
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]
ForceHideMinimapFrame(f)
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
ForceHideMinimapFrame(child)
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 IsMapStateProtected() then
return
end
if SetMapToCurrentZone then
if SFrames and SFrames.CallWithPreservedBattlefieldMinimap then
SFrames:CallWithPreservedBattlefieldMinimap(SetMapToCurrentZone)
else
pcall(SetMapToCurrentZone)
end
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