Files
ShaguTweaks-ClassicAPI/mods/unitframes-hide-player-resources.lua
T

250 lines
12 KiB
Lua

local _G = ShaguTweaks.GetGlobalEnv()
local T = ShaguTweaks.T
local API = ShaguTweaks.API
local module = ShaguTweaks:register({
title = T["Hide Player Frame Resources"],
description = T["Hides the original player health and power bars, leaving the clean round portrait and name. Hold Ctrl+Shift+Alt to drag the name independently; right-click with those keys held to reset it. Personal Resource Display is independent."],
expansions = { ["vanilla"] = true }, category = T["Unit Frames"], enabled = nil,
})
local function MoveRegion(region, holder, x, y)
if not region then return end
region:SetParent(holder)
region:ClearAllPoints()
region:SetPoint("TOPLEFT", holder, "TOPLEFT", x, y)
end
module.enable = function(self)
if self.scheduled then return end
self.scheduled = true
local function Setup()
if self.installed or not PlayerFrame or not PlayerPortrait or not PlayerFrameTexture then return end
if not PlayerPortrait:GetLeft() or not PlayerFrame:GetLeft() then return end
self.installed = true
local width = PlayerFrameHealthBar:GetWidth()
local portraitLeft, portraitTop = PlayerPortrait:GetLeft() - 8, PlayerPortrait:GetTop() + 4
local function Holder(key, w, h, x, y)
local holder = CreateFrame("Frame", "ShaguTweaksPlayer" .. key, PlayerFrame)
holder:SetWidth(w); holder:SetHeight(h)
holder:SetFrameLevel(PlayerFrame:GetFrameLevel() + 3)
holder:SetPoint("TOPLEFT", PlayerFrame, "TOPLEFT", x - PlayerFrame:GetLeft(), y - PlayerFrame:GetTop())
return holder
end
local portrait = Holder("Portrait", 80, 80, portraitLeft, portraitTop)
local name = Holder("Name", width + 8, 23, portraitLeft + 85, portraitTop - 14)
ShaguTweaks.PlayerFrameResourcesLayout = { portrait = portrait, name = name }
ShaguTweaks_config.PlayerFrameResources = ShaguTweaks_config.PlayerFrameResources or {}
local positions = ShaguTweaks_config.PlayerFrameResources
local nameX, nameY = portraitLeft + 85 - PlayerFrame:GetLeft(), portraitTop - 14 - PlayerFrame:GetTop()
local function PositionName()
name:ClearAllPoints()
if positions.Name then
name:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", positions.Name.x, positions.Name.y)
else
name:SetPoint("TOPLEFT", PlayerFrame, "TOPLEFT", nameX, nameY)
end
end
local dragging, dropped
local function StopName()
if not dragging then return end
name:StopMovingOrSizing()
name:SetUserPlaced(false)
dragging, dropped = nil, true
local x, y = name:GetLeft(), name:GetTop()
if x and y then positions.Name = { x = x, y = y } end
PositionName()
end
name:SetMovable(true)
name:SetClampedToScreen(true)
name:EnableMouse(true)
name:RegisterForDrag("LeftButton")
name:SetScript("OnDragStart", function()
if not API.AreMoveModifiersDown() then return end
dragging, dropped = true, nil
name:StartMoving()
end)
name:SetScript("OnDragStop", StopName)
name:SetScript("OnHide", StopName)
name:SetScript("OnMouseUp", function()
if API.AreMoveModifiersDown() and arg1 == "RightButton" then
StopName()
positions.Name, dropped = nil, nil
PositionName()
elseif dragging then
StopName()
dropped = nil
elseif dropped then
dropped = nil
elseif PlayerFrame_OnClick then
-- Retain native unit clicks even after the name is moved away.
local previous = this
this = PlayerFrame
PlayerFrame_OnClick(arg1)
this = previous
end
end)
PositionName()
-- Split the native artwork before changing its source texture's anchors.
-- Preserve its UV orientation (the player's stock artwork is mirrored).
local art = PlayerFrameTexture
local path = art:GetTexture()
local u, v, unused, bottom, right = art:GetTexCoord()
local artWidth, artHeight = PlayerFrame:GetWidth(), PlayerFrame:GetHeight()
local r, g, b, a = art:GetVertexColor()
local function Crop(holder, x, y, w, h)
local texture = holder:CreateTexture(nil, "OVERLAY")
texture:SetTexture(path)
texture:SetTexCoord(u + (right-u)*x/artWidth, u + (right-u)*(x+w)/artWidth,
v + (bottom-v)*y/artHeight, v + (bottom-v)*(y+h)/artHeight)
texture:SetAllPoints(holder)
texture:SetVertexColor(r, g, b, a)
return texture
end
-- Keep the native level badge on the left. Complete the right side from
-- the clean upper-left quadrant, leaving space for the live resting icon
-- without mirroring a second level badge into the artwork. The native
-- resting/combat icon shares the original left badge's position.
portrait.art = Crop(portrait, 34, 8, 40, 72)
portrait.artRight = Crop(portrait, 74, 8, -40, 36)
portrait.artBottomRight = Crop(portrait, 74, 44, -40, -36)
local function Piece(texture, x, y, height)
texture:ClearAllPoints()
texture:SetPoint("TOPLEFT", portrait, "TOPLEFT", x, y)
texture:SetWidth(40)
texture:SetHeight(height)
end
Piece(portrait.art, 0, 0, 72)
Piece(portrait.artRight, 40, 0, 36)
Piece(portrait.artBottomRight, 40, -36, 36)
-- The native lower-left quadrant includes a dark rectangular shadow
-- beside the level badge. Use the same clean quadrant as the lower right,
-- then restore only the badge circle, not its surrounding shadow.
portrait.badge = Crop(portrait, 37, 50, 32, 32)
portrait.badge:ClearAllPoints()
portrait.badge:SetPoint("TOPLEFT", portrait, "TOPLEFT", 3, -42)
portrait.badge:SetWidth(32)
portrait.badge:SetHeight(32)
if type(portrait.badge.SetMask) == "function" then
portrait.art:SetTexCoord(u + (right-u)*34/artWidth, u + (right-u)*74/artWidth,
v + (bottom-v)*8/artHeight, v + (bottom-v)*44/artHeight)
Piece(portrait.art, 0, 0, 36)
portrait.artBottomLeft = Crop(portrait, 34, 44, 40, -36)
Piece(portrait.artBottomLeft, 0, -36, 36)
portrait.badge:SetMask("Interface\\CharacterFrame\\TempPortraitAlphaMask")
-- Keep the badge above every ring piece but below the number/state icons.
portrait.badgeOverlay = CreateFrame("Frame", nil, portrait)
portrait.badgeOverlay:SetAllPoints(portrait)
portrait.badgeOverlay:SetFrameLevel(portrait:GetFrameLevel() + 1)
portrait.badge:SetParent(portrait.badgeOverlay)
else
-- Older clients retain the original left half and its native badge.
portrait.badge:Hide()
end
-- The combined frame texture has a portrait arc at the left ends of its
-- bars. Give the separate name strip a rounded Blizzard border.
local border = {
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
edgeSize = 12, tile = true, tileSize = 8,
insets = { left = 3, right = 3, top = 3, bottom = 3 },
}
local color = ShaguTweaks.UIBorder
name:SetBackdrop(border)
name:SetBackdropBorderColor(color and color.r or 1, color and color.g or 1,
color and color.b or 1, 1)
-- Keep status/role indicators with the portrait. Their native event
-- handlers and parent visibility continue running unchanged.
local indicators = { "PlayerHitIndicator", "PlayerPVPIcon", "PlayerPVPIconHitArea",
"PlayerLeaderIcon", "PlayerMasterIcon", "PlayerRestIcon", "PlayerAttackIcon",
"PlayerAttackBackground", "PlayerStatusGlow", "PlayerFrameGroupIndicator" }
local indicatorPoints = {}
for i = 1, table.getn(indicators) do
local region = _G[indicators[i]]
if region and region:GetLeft() and region:GetTop() then
indicatorPoints[i] = { region:GetLeft() - portraitLeft, region:GetTop() - portraitTop }
end
end
-- Snapshot first: some indicators are anchored to other indicators.
for i = 1, table.getn(indicators) do
local point = indicatorPoints[i]
if point then MoveRegion(_G[indicators[i]], portrait, point[1], point[2]) end
end
MoveRegion(PlayerPortrait, portrait, 8, -4)
if _G.PlayerLevelText then
-- Put the native text above the ring and portrait, centered over the
-- native left-hand badge. The stock level-update code keeps owning it.
local levelX, levelY = 19, -58
if PlayerLevelText.GetCenter then
local x, y = PlayerLevelText:GetCenter()
if x and y then levelX, levelY = x - portraitLeft, y - portraitTop end
end
portrait.levelOverlay = CreateFrame("Frame", nil, portrait)
portrait.levelOverlay:SetAllPoints(portrait)
portrait.levelOverlay:SetFrameLevel(portrait:GetFrameLevel() + 5)
PlayerLevelText:SetParent(portrait.levelOverlay)
PlayerLevelText:ClearAllPoints()
PlayerLevelText:SetPoint("CENTER", portrait.levelOverlay, "TOPLEFT", levelX, levelY)
PlayerLevelText:SetDrawLayer("BACKGROUND")
PlayerLevelText:SetAlpha(1)
PlayerLevelText:SetText(UnitLevel("player"))
PlayerLevelText:Show()
-- Keep the level above the ring but BELOW its native state icons.
-- Their existing Show/Hide logic then covers the number while resting
-- or in combat and reveals it again without adding another event loop.
for _, key in ipairs({ "PlayerRestIcon", "PlayerAttackIcon", "PlayerAttackBackground", "PlayerStatusGlow" }) do
local indicator = _G[key]
if indicator then indicator:SetParent(portrait.levelOverlay) end
end
end
local playerName = PlayerFrame.name or _G.PlayerName
if playerName then
playerName:SetParent(name)
playerName:ClearAllPoints()
playerName:SetPoint("CENTER", name, "CENTER", 0, 0)
end
-- Big Health deliberately hides the stock name background. Keep its
-- color source for that module, but draw a separate class strip here.
name.classBackground = name:CreateTexture(nil, "BACKGROUND")
name.classBackground:SetPoint("TOPLEFT", name, "TOPLEFT", 4, -3)
name.classBackground:SetPoint("BOTTOMRIGHT", name, "BOTTOMRIGHT", -4, 3)
local healthTexture = PlayerFrameHealthBar:GetStatusBarTexture()
name.classBackground:SetTexture(healthTexture and healthTexture:GetTexture()
or "Interface\\TargetingFrame\\UI-StatusBar")
local _, class = UnitClass("player")
local palette = ShaguTweaks.ModernClassColors or RAID_CLASS_COLORS
local classColor = palette and palette[class]
local cr, cg, cb = PlayerFrameHealthBar:GetStatusBarColor()
name.classBackground:SetVertexColor(classColor and classColor.r or cr,
classColor and classColor.g or cg, classColor and classColor.b or cb, 1)
if ShaguTweaks_config[T["Hide Player Name"]] == 1 then name:Hide() end
-- Keep native bar objects and events alive. Copies may still mirror them.
local function Suppress(region)
if not region then return end
local setAlpha = region.SetAlpha
setAlpha(region, 0)
ShaguTweaks.hooksecurefunc(region, "SetAlpha", function(object) setAlpha(object, 0) end)
end
Suppress(PlayerFrameTexture)
Suppress(_G.PlayerFrameBackground)
Suppress(_G.PlayerFrameNameBackground)
Suppress(PlayerFrameHealthBar)
Suppress(PlayerFrameManaBar)
Suppress(_G.PlayerFrameAlternatePowerBar)
if PlayerStatusTexture then
MoveRegion(PlayerStatusTexture, portrait, 1, 0)
local function CropStatus()
PlayerStatusTexture:SetTexCoord(0, 72/256, 0, 66/128)
PlayerStatusTexture:SetWidth(72)
PlayerStatusTexture:SetHeight(66)
end
if type(PlayerStatusTexture.SetMask) == "function" then
PlayerStatusTexture:SetMask("Interface\\CharacterFrame\\TempPortraitAlphaMask")
end
ShaguTweaks.hooksecurefunc("PlayerFrame_UpdateStatus", CropStatus)
CropStatus()
end
end
API.AfterWorldReady(Setup, true)
end