-
Notifications
You must be signed in to change notification settings - Fork 50
Expand file tree
/
Copy pathEllesmereUI_Visibility.lua
More file actions
168 lines (150 loc) · 6.45 KB
/
EllesmereUI_Visibility.lua
File metadata and controls
168 lines (150 loc) · 6.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
-------------------------------------------------------------------------------
-- EllesmereUI_Visibility.lua
-- Shared visibility dispatcher. Each module (Minimap, Friends, QuestTracker,
-- Cursor) registers its own update function here; this file owns the event
-- frame, combat state, mouseover polling, and the global bridge names.
-------------------------------------------------------------------------------
local EUI = _G.EllesmereUI or {}
_G.EllesmereUI = EUI
-------------------------------------------------------------------------------
-- Combat state (single source of truth)
-------------------------------------------------------------------------------
local _inCombat = false
local function IsInCombat() return _inCombat end
EUI.IsInCombat = IsInCombat
-------------------------------------------------------------------------------
-- Eval helper (shared by all modules' cfg checks)
-------------------------------------------------------------------------------
-- Returns true = show, false = hide, "mouseover" = mouseover mode
local function EvalVisibility(cfg)
if not cfg then return true end
if EUI.CheckVisibilityOptions and EUI.CheckVisibilityOptions(cfg) then
return false
end
local mode = cfg.visibility or "always"
if mode == "mouseover" then return "mouseover" end
if mode == "always" then return true end
if mode == "never" then return false end
if mode == "in_combat" then return _inCombat end
if mode == "out_of_combat" then return not _inCombat end
local inGroup = IsInGroup()
local inRaid = IsInRaid()
if mode == "in_raid" then return inRaid end
if mode == "in_party" then return inGroup and not inRaid end
if mode == "solo" then return not inGroup end
return true
end
EUI.EvalVisibility = EvalVisibility
-------------------------------------------------------------------------------
-- Updater registry
-------------------------------------------------------------------------------
local updaters = {}
-- Register a module's update function. Called whenever visibility state may
-- have changed (combat/zone/group/target change). The function should read
-- its own DB state and Show/Hide its frame accordingly.
function EUI.RegisterVisibilityUpdater(fn)
if type(fn) ~= "function" then return end
updaters[#updaters + 1] = fn
end
function EUI.UnregisterVisibilityUpdater(fn)
for i = #updaters, 1, -1 do
if updaters[i] == fn then
table.remove(updaters, i)
return
end
end
end
-- Mouseover poll registry: each entry is { frame=, visible=, isActive=fn }.
-- isActive returns true when that frame currently wants mouseover behavior.
local mouseoverTargets = {}
function EUI.RegisterMouseoverTarget(frame, isActive)
if not frame or type(isActive) ~= "function" then return end
mouseoverTargets[#mouseoverTargets + 1] = { frame = frame, visible = false, isActive = isActive }
end
-------------------------------------------------------------------------------
-- Dispatcher
-------------------------------------------------------------------------------
local function RequestVisibilityUpdate()
for i = 1, #updaters do
local ok = pcall(updaters[i])
if not ok then
-- swallow; one bad updater should not take down the rest
end
end
end
EUI.RequestVisibilityUpdate = RequestVisibilityUpdate
-- Deferred callback so we don't re-allocate a closure on every event
local function DeferredRequest()
RequestVisibilityUpdate()
end
-------------------------------------------------------------------------------
-- Event frame
-------------------------------------------------------------------------------
local visFrame = CreateFrame("Frame")
visFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
visFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
visFrame:RegisterEvent("PLAYER_TARGET_CHANGED")
visFrame:RegisterEvent("PLAYER_MOUNT_DISPLAY_CHANGED")
visFrame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
visFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
visFrame:RegisterEvent("GROUP_ROSTER_UPDATE")
visFrame:RegisterEvent("UPDATE_SHAPESHIFT_FORM")
visFrame:SetScript("OnEvent", function(_, event)
if event == "PLAYER_REGEN_DISABLED" then
_inCombat = true
elseif event == "PLAYER_REGEN_ENABLED" then
_inCombat = false
end
C_Timer.After(0, DeferredRequest)
end)
-------------------------------------------------------------------------------
-- Mouseover poll
-------------------------------------------------------------------------------
local mouseoverPoll = CreateFrame("Frame")
-- Cursor-in-bounds check (works on hidden frames using saved position/size)
local function IsCursorOver(frame)
if not frame.GetRect then return false end
local l, b, w, h = frame:GetRect()
if not l then return false end
local es = frame:GetEffectiveScale()
local cx, cy = GetCursorPosition()
cx, cy = cx / es, cy / es
return cx >= l and cx <= l + w and cy >= b and cy <= b + h
end
local moElapsed = 0
mouseoverPoll:SetScript("OnUpdate", function(_, dt)
moElapsed = moElapsed + dt
if moElapsed < 0.15 then return end
moElapsed = 0
for i = 1, #mouseoverTargets do
local t = mouseoverTargets[i]
local frame = t.frame
if frame then
if t.isActive() then
t._wasActive = true
local over = IsCursorOver(frame)
if over and not t.visible then
t.visible = true
frame:SetAlpha(1); frame:EnableMouse(true); frame:Show()
elseif not over and t.visible then
t.visible = false
frame:Hide()
end
elseif t._wasActive then
-- isActive just turned off -- clear tracking state and let
-- UpdateVisibility handle the alpha for the new mode.
t._wasActive = false
t.visible = nil
end
end
end
end)
-------------------------------------------------------------------------------
-- Compat globals (kept for the many call sites already using them)
-------------------------------------------------------------------------------
_G._EBS_InCombat = IsInCombat
_G._EBS_EvalVisibility = EvalVisibility
_G._EBS_UpdateVisibility = RequestVisibilityUpdate
-- UpdateVisEventRegistration is a no-op now -- the events are always on,
-- but the overhead is trivial (a handful of rarely-firing events).
_G._EBS_UpdateVisEventRegistration = function() end