001062c - Refector indicators to be more flexible
[wowui.git] / OmaRF / RaidFrame.lua
1 -- RaidFrame.lua
2 local _;
3 local unpack, pairs, rawget = unpack, pairs, rawget;
4 local format = string.format;
5 local UnitHealthMax, UnitPowerMax = UnitHealthMax, UnitPowerMax;
6 local UnitInRange = UnitInRange;
7 local InCombatLockdown = InCombatLockdown;
8 local CreateFrame, RegisterStateDriver, RegisterUnitWatch = CreateFrame, RegisterStateDriver, RegisterUnitWatch;
9 local STANDARD_TEXT_FONT = STANDARD_TEXT_FONT;
10 local GameTooltip = nil;
11 local GameTooltip_SetDefaultAnchor = nil;
12
13 local registerEvents = OmaRFEvents.RegisterEvents;
14 local registerUnitEvents = OmaRFEvents.RegisterUnitEvents;
15 local unitEvent = OmaRFEvents.UnitEvent;
16 local setupIndicators = OmaRFIndicators.SetupIndicators;
17
18 local Settings = OmaRFSettings;
19 local baseColor = Settings.BaseColor;
20 local bgColor = Settings.BgColor;
21 local healthColor = Settings.HealthColor;
22 local shieldColor = Settings.ShieldColor;
23 local shieldhlColor = Settings.ShieldhlColor;
24 local healpredColor = Settings.HealpredColor;
25 local healabsorbColor = Settings.HealabsorbColor;
26 local width, height = Settings.Width, Settings.Height;
27 -- placeholders with visible values when error happens
28 local anchorX, anchorY = 10, 10;
29 local attributes = {};
30
31 local CFrame = CreateFrame("Frame", "OmaRFFrame", UIParent);
32 local inheritedFrames = "SecureUnitButtonTemplate,SecureHandlerStateTemplate";
33 local class = nil;
34 local party = {};
35 local raid = {};
36
37 local M = {};
38 OmaRaidFrame = M;
39
40 local function unitUpdate(self, elapsed)
41     -- there's no in/out of range event, have to check each frame
42     -- from FrameXML/CompactUnitFrame.lua
43     local inRange, checked = UnitInRange(self.displayed);
44     if checked and not inRange then
45         self:SetAlpha(0.55);
46     else
47         self:SetAlpha(1);
48     end
49 end
50
51 local function frameShow(frame)
52     registerEvents(frame);
53     registerUnitEvents(frame);
54     frame:SetScript("OnUpdate", unitUpdate);
55     unitEvent(frame, "UPDATE_ALL_BARS");
56 end
57
58 local function frameHide(frame)
59     frame:UnregisterAllEvents();
60     frame:SetScript("OnUpdate", nil);
61 end
62
63 local function showTooltip(secure)
64     GameTooltip_SetDefaultAnchor(GameTooltip, secure);
65     GameTooltip:SetUnit(secure:GetAttribute("unit"));
66 end
67
68 local function hideTooltip(secure)
69     GameTooltip:FadeOut();
70 end
71
72 local function setupFrame(frame, secure, unit)
73     secure:SetAttribute("unit", unit);
74     frame:SetAttribute("unit", unit);
75     frame.unit = unit;
76     frame.displayed = unit;
77     -- hide frame to get initial frameShow call
78     frame:Hide();
79     if unit == "player" then frame.vehicle = "vehicle"
80     else frame.vehicle = unit.."pet" end
81     -- create visuals
82     secure:SetWidth(width+2);
83     secure:SetHeight(height+2);
84     frame:SetWidth(width+2);
85     frame:SetHeight(height+2);
86     frame.base = frame:CreateTexture(nil, "BACKGROUND");
87     frame.base:SetAllPoints();
88     frame.base:SetColorTexture(1, 1, 1);
89     frame.base:SetVertexColor(unpack(baseColor));
90     frame.background = frame:CreateTexture(nil, "BACKGROUND", nil, 1);
91     frame.background:SetPoint("TOPLEFT", frame, "TOPLEFT", 1, -1);
92     frame.background:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -1, 1);
93     frame.background:SetColorTexture(unpack(bgColor));
94     frame.health = frame:CreateTexture(nil, "BORDER");
95     frame.health:SetTexture("Interface\\RaidFrame\\Raid-Bar-Hp-Fill");
96     frame.health:SetPoint("TOPLEFT", frame.background, "TOPLEFT");
97     frame.health:SetPoint("BOTTOMLEFT", frame.background, "BOTTOMLEFT");
98     frame.health:SetVertexColor(unpack(healthColor));
99     frame.mana = frame:CreateTexture(nil, "BORDER");
100     frame.mana:SetPoint("TOPLEFT", frame.background, "BOTTOMLEFT", 0, 2);
101     frame.mana:SetPoint("BOTTOMLEFT", frame.background, "BOTTOMLEFT");
102     frame.mana:SetColorTexture(1, 1, 1);
103     frame.mana:Hide();
104     frame.shield = frame:CreateTexture(nil, "BORDER");
105     frame.shield:SetPoint("TOPLEFT", frame.health, "TOPRIGHT");
106     frame.shield:SetPoint("BOTTOMLEFT", frame.health, "BOTTOMRIGHT");
107     frame.shield:SetColorTexture(unpack(shieldColor));
108     frame.shield:Hide();
109     frame.shieldhl = frame:CreateTexture(nil, "ARTWORK");
110     frame.shieldhl:SetPoint("TOPLEFT", frame.background, "TOPRIGHT", -1, 0);
111     frame.shieldhl:SetPoint("BOTTOMRIGHT", frame.background, "BOTTOMRIGHT", 1, 0);
112     frame.shieldhl:SetColorTexture(unpack(shieldhlColor));
113     frame.shieldhl:Hide();
114     frame.healpred = frame:CreateTexture(nil, "ARTWORK");
115     frame.healpred:SetPoint("TOPLEFT", frame.health, "TOPRIGHT");
116     frame.healpred:SetPoint("BOTTOMLEFT", frame.health, "BOTTOMRIGHT");
117     frame.healpred:SetColorTexture(unpack(healpredColor));
118     frame.healpred:Hide();
119     frame.healabsorb = frame:CreateTexture(nil, "ARTWORK");
120     frame.healabsorb:SetPoint("TOPRIGHT", frame.health, "TOPRIGHT");
121     frame.healabsorb:SetPoint("BOTTOMRIGHT", frame.health, "BOTTOMRIGHT");
122     frame.healabsorb:SetColorTexture(unpack(healabsorbColor));
123     frame.healabsorb:Hide();
124     frame.role = frame:CreateTexture(nil, "ARTWORK");
125     frame.role:SetPoint("BOTTOMRIGHT", frame.background, "BOTTOMRIGHT", -2, 2);
126     frame.role:SetPoint("TOPLEFT", frame.background, "BOTTOMRIGHT", -14, 14);
127     frame.role:SetTexture("Interface\\LFGFRAME\\LFGROLE");
128     frame.role:Hide();
129     frame.overlay = frame:CreateTexture(nil, "ARTWORK", nil, 1);
130     frame.overlay:SetPoint("TOPLEFT", frame.background, "TOPLEFT");
131     frame.overlay:SetPoint("BOTTOMRIGHT", frame.background, "BOTTOMRIGHT");
132     frame.overlay:SetColorTexture(1, 1, 1);
133     frame.overlay:Hide();
134     frame.name = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight");
135     frame.name:SetPoint("CENTER", frame.background, "CENTER", 0, 11);
136     frame.text = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlight");
137     frame.text:SetFont(STANDARD_TEXT_FONT, 13);
138     frame.text:SetPoint("CENTER", frame.background, "CENTER", 0, -1);
139     frame.text:Hide();
140     frame.rez = frame:CreateTexture(nil, "OVERLAY");
141     frame.rez:SetPoint("TOPLEFT", frame.background, "CENTER", -12, 12);
142     frame.rez:SetPoint("BOTTOMRIGHT", frame.background, "CENTER", 12, -12);
143     frame.rez:SetTexture("Interface\\RaidFrame\\Raid-Icon-Rez");
144     frame.rez:Hide();
145     frame.ready = frame:CreateTexture(nil, "OVERLAY");
146     frame.ready:SetPoint("TOPLEFT", frame.background, "BOTTOMLEFT", 0, 14);
147     frame.ready:SetPoint("BOTTOMRIGHT", frame.background, "BOTTOMLEFT", 14, 0);
148     frame.ready:Hide();
149     -- set up indicators
150     setupIndicators(frame, class);
151     -- set scripts
152     frame:SetScript("OnShow", frameShow);
153     frame:SetScript("OnHide", frameHide);
154     frame:SetScript("OnEvent", unitEvent);
155     secure:SetScript("OnEnter", showTooltip);
156     secure:SetScript("OnLeave", hideTooltip);
157     -- set attributes
158     secure:RegisterForClicks("AnyDown");
159     for attr, val in pairs(attributes) do
160         secure:SetAttribute(attr, val);
161     end
162     -- rest give target and menu
163     secure:SetAttribute("*type1", "target");
164     secure:SetAttribute("*type2", "togglemenu");
165 end
166
167 -- vehicle toggle from Shadowed Unit Frames
168 local vehicletoggle = [=[
169     local unit = self:GetAttribute("unit");
170     if unit and newstate == "vehicle" and not UnitTargetsVehicleInRaidUI(unit) then
171         self:SetAttribute("toggleForVehicle", false);
172     else
173         self:SetAttribute("toggleForVehicle", true);
174     end
175 ]=]
176
177 local function initializeParty(parent)
178     local secure = CreateFrame("Button", "OmaPartySecure0", parent, inheritedFrames);
179     local frame = CreateFrame("Frame", "OmaParty0", parent);
180     local unit = "player";
181     secure:SetPoint("TOPLEFT", parent, "TOPLEFT");
182     frame:SetPoint("TOPLEFT", parent, "TOPLEFT");
183     setupFrame(frame, secure, unit);
184     RegisterStateDriver(frame, "visibility", "[@player,group:raid] hide; show");
185     RegisterStateDriver(secure, "visibility", "[@player,group:raid] hide; show");
186     RegisterStateDriver(secure, "vehicleui", "[vehicleui] vehicle; no");
187     secure:SetAttribute("_onstate-vehicleui", vehicletoggle);
188     party[0] = {secure=secure, frame=frame};
189     for i = 1,4 do
190         local secure = CreateFrame("Button", "OmaPartySecure"..i, parent, inheritedFrames);
191         local frame = CreateFrame("Frame", "OmaParty"..i, parent);
192         local unit = "party"..i;
193         secure:SetPoint("TOPLEFT", party[i-1].secure, "TOPRIGHT");
194         frame:SetPoint("TOPLEFT", party[i-1].frame, "TOPRIGHT");
195         setupFrame(frame, secure, unit);
196         local visible = format("[@%s,exists,group:raid] hide; [@%s,exists] show; hide", unit, unit);
197         local vehicle = format("[@%s,unithasvehicleui] vehicle; no", unit);
198         RegisterStateDriver(frame, "visibility", visible);
199         RegisterStateDriver(secure, "visibility", visible);
200         RegisterStateDriver(secure, "vehicleui", vehicle);
201         secure:SetAttribute("_onstate-vehicleui", vehicletoggle);
202         party[i] = {secure=secure, frame=frame};
203     end
204 end
205
206 local function initializeRaid(parent)
207     local secure = CreateFrame("Button", "OmaRaidSecure1", parent, inheritedFrames);
208     local frame = CreateFrame("Frame", "OmaRaid1", parent);
209     local unit = "raid1";
210     secure:SetPoint("TOPLEFT", parent, "TOPLEFT");
211     frame:SetPoint("TOPLEFT", parent, "TOPLEFT");
212     setupFrame(frame, secure, unit);
213     RegisterUnitWatch(frame);
214     RegisterUnitWatch(secure);
215     local vehicle = format("[@%s,unithasvehicleui] vehicle; no", unit);
216     RegisterStateDriver(secure, "vehicleui", vehicle);
217     secure:SetAttribute("_onstate-vehicleui", vehicletoggle);
218     raid[1] = {secure=secure, frame=frame};
219     for y = 1,7 do
220         local i = y*5+1;
221         local secure = CreateFrame("Button", "OmaRaidSecure"..i, parent, inheritedFrames);
222         local frame = CreateFrame("Frame", "OmaRaid"..i, parent);
223         local unit = "raid"..i;
224         secure:SetPoint("TOPLEFT", raid[i-5].secure, "BOTTOMLEFT");
225         frame:SetPoint("TOPLEFT", raid[i-5].frame, "BOTTOMLEFT");
226         setupFrame(frame, secure, unit);
227         RegisterUnitWatch(frame);
228         RegisterUnitWatch(secure);
229         local vehicle = format("[@%s,unithasvehicleui] vehicle; no", unit);
230         RegisterStateDriver(secure, "vehicleui", vehicle);
231         secure:SetAttribute("_onstate-vehicleui", vehicletoggle);
232         raid[i] = {secure=secure, frame=frame};
233     end
234     for y = 0,7 do
235         for x = 1,4 do
236             local i = y*5+x+1;
237             local secure = CreateFrame("Button", "OmaRaidSecure"..i, parent, inheritedFrames);
238             local frame = CreateFrame("Frame", "OmaRaid"..i, parent);
239             local unit = "raid"..i;
240             secure:SetPoint("TOPLEFT", raid[i-1].secure, "TOPRIGHT");
241             frame:SetPoint("TOPLEFT", raid[i-1].frame, "TOPRIGHT");
242             setupFrame(frame, secure, unit);
243             RegisterUnitWatch(frame);
244             RegisterUnitWatch(secure);
245             local vehicle = format("[@%s,unithasvehicleui] vehicle; no", unit);
246             RegisterStateDriver(secure, "vehicleui", vehicle);
247             secure:SetAttribute("_onstate-vehicleui", vehicletoggle);
248             raid[i] = {secure=secure, frame=frame};
249         end
250     end
251 end
252
253 local function initializeFocus(parent)
254     local secure = CreateFrame("Button", "OmaFocusSecure", parent, inheritedFrames);
255     local frame = CreateFrame("Frame", "OmaFocus", parent);
256     local unit = "focus";
257     secure:SetPoint("BOTTOMLEFT", parent, "TOPLEFT");
258     frame:SetPoint("BOTTOMLEFT", parent, "TOPLEFT");
259     setupFrame(frame, secure, unit);
260     RegisterUnitWatch(frame);
261     RegisterUnitWatch(secure);
262     local vehicle = format("[@%s,unithasvehicleui] vehicle; no", unit);
263     RegisterStateDriver(secure, "vehicleui", vehicle);
264     secure:SetAttribute("_onstate-vehicleui", vehicletoggle);
265 end
266
267 local function loadCharSettings()
268     anchorX, anchorY = Settings.Character.AnchorX, Settings.Character.AnchorY;
269     attributes = Settings.Character.Clickheal;
270 end
271
272 local function initialize()
273     -- let other addons hook these to anchor tooltip elsewhere
274     GameTooltip = _G["GameTooltip"];
275     GameTooltip_SetDefaultAnchor = _G["GameTooltip_SetDefaultAnchor"];
276     loadCharSettings();
277     class = UnitClass("player");
278     CFrame:SetPoint("CENTER", nil, "CENTER", anchorX, anchorY);
279     CFrame:SetHeight((height+2)*8);
280     CFrame:SetWidth((width+2)*5);
281     initializeParty(CFrame);
282     initializeRaid(CFrame);
283     initializeFocus(CFrame);
284 end
285
286 -- hiding Blizzard frames somewhat based on ShadowedUF
287 local function hideBlizzardRaidButton()
288     if InCombatLockdown() then return end
289     local manager = CompactRaidFrameManager;
290     -- remove show and unlock buttons from manager
291     manager.displayFrame.hiddenModeToggle:Hide();
292     manager.displayFrame.lockedModeToggle:Hide();
293 end
294
295 local hidden = false;
296 local function hideBlizzardRaid()
297     if hidden then return end
298     hidden = true;
299     local function hide()
300         if InCombatLockdown() then return end
301         CompactRaidFrameContainer:Hide();
302         local shown = CompactRaidFrameManager_GetSetting("IsShown");
303         if shown and shown ~= "0" then
304             CompactRaidFrameManager_SetSetting("IsShown", "0");
305         end
306     end
307
308     CompactRaidFrameContainer:UnregisterAllEvents();
309     -- there may still be frames created at startup getting events
310     for i=1,MAX_RAID_MEMBERS do
311         local frame = _G["CompactRaidFrame"..i];
312         if not frame then break end
313         frame:UnregisterAllEvents();
314     end
315     hooksecurefunc("CompactRaidFrameManager_UpdateShown", hide);
316     hide();
317     CompactRaidFrameContainer:HookScript("OnShow", hide);
318     hooksecurefunc("CompactRaidFrameManager_UpdateOptionsFlowContainer", hideBlizzardRaidButton);
319     hideBlizzardRaidButton();
320
321     -- hide focus frame
322     for _, frame in pairs({FocusFrame, FocusFrameToT}) do
323         frame:UnregisterAllEvents();
324         frame.healthbar:UnregisterAllEvents();
325         frame.manabar:UnregisterAllEvents();
326         if frame.spellbar then frame.spellbar:UnregisterAllEvents() end
327         if frame.powerBarAlt then frame.powerBarAlt:UnregisterAllEvents() end
328         frame:Hide();
329     end
330 end
331
332 CFrame:RegisterEvent("PLAYER_LOGIN");
333 CFrame:RegisterEvent("PLAYER_REGEN_ENABLED");
334 CFrame:SetScript("OnEvent", function(self, event, addon)
335     if event == "PLAYER_LOGIN" then
336         OmaRFLoadChar();
337         hideBlizzardRaid();
338         initialize();
339     elseif event == "PLAYER_REGEN_ENABLED" then
340         -- if CompactRaidFrameManager_UpdateOptionsFlowContainer was called in combat
341         -- couldn't hide the button
342         hideBlizzardRaidButton();
343     end
344 end);