a7e766a - Start player frame modification
[wowui.git] / OmaRF / Indicators.lua
1 local media = LibStub:GetLibrary("LibSharedMedia-3.0");
2 local f = OmaRF.frames;
3 local positions = OmaRF.positions;
4 local pad = 2;
5 local paddings = {
6     TOPLEFT = {pad, -pad},
7     TOPRIGHT = {-pad, -pad},
8     CENTER = {0, 0},
9     BOTTOMLEFT = {pad, pad},
10     BOTTOMRIGHT = {-pad, pad}
11 };
12 local watchedAuras; -- all watched auras
13 local auraFilters = {"HELPFUL", "HARMFUL"};
14 local DEFAULT_ICON = "Interface\\AddOns\\OmaRF\\images\\rhomb";
15 local _;
16
17 -- global functions used every update
18 local C_TimerAfter = C_Timer.After;
19 local GetTime = GetTime;
20 local UnitAura = UnitAura;
21 local UnitIsPlayer = UnitIsPlayer;
22 local UnitIsConnected = UnitIsConnected;
23 local UnitIsDeadOrGhost = UnitIsDeadOrGhost;
24 local CompactRaidFrameContainer_ApplyToFrames = CompactRaidFrameContainer_ApplyToFrames;
25 local format = string.format;
26 local unpack = unpack;
27
28 -- list of important auras TODO try to use spellIDs
29 local centerAuras = {
30     "Power Word: Shield"
31 };
32
33 local function configureIndicators(frame, name)
34     local frameName = name or frame:GetName();
35     if not f[frameName] then return end
36
37     local config = OmaRF.db.profile.indicators;
38     local font = media and media:Fetch('font', config.indicatorFont) or STANDARD_TEXT_FONT;
39     for pos, ind in pairs(f[frameName]) do
40         ind.text:SetFont(font, config[pos]["textSize"]);
41         ind.text:SetTextColor(unpack(config[pos]["textColor"]));
42         ind.icon:SetWidth(config[pos]["iconSize"]);
43         ind.icon:SetHeight(config[pos]["iconSize"]);
44         ind.icon:SetTexture(DEFAULT_ICON);
45         ind.icon:SetVertexColor(unpack(config[pos]["iconColor"]));
46         if config[pos]["showIcon"] then
47             ind.icon:Show();
48         else
49             ind.icon:Hide();
50         end
51     end
52 end
53
54 -- Create the FontStrings used for indicators
55 local function setupCompactUnitFrame(frame, name)
56     f[name] = {};
57     for _, pos in ipairs(positions) do
58         f[name][pos] = {};
59         f[name][pos].text = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall");
60         f[name][pos].text:SetPoint(pos, frame, pos, paddings[pos][1], paddings[pos][2]);
61         f[name][pos].icon = frame:CreateTexture(nil, "OVERLAY");
62         f[name][pos].icon:SetPoint(pos, frame, pos, paddings[pos][1], paddings[pos][2]);
63     end
64     configureIndicators(frame, name);
65 end
66
67 -- Check the indicators on a frame and update the times on them
68 local function updateIndicators(frame)
69     local frameName = frame:GetName();
70     local unit = frame.unit;
71     if not unit then return end -- possible if the frame is just being hidden
72
73     -- Create indicators if needed
74     if not f[frameName] then setupCompactUnitFrame(frame, frameName) end
75     -- Reset current
76     for _, ind in pairs(f[frameName]) do
77         ind.text:SetText("");
78         ind.icon:SetTexture("");
79     end
80     -- Hide if unit is dead/disconnected
81     if (not UnitIsConnected(unit)) or UnitIsDeadOrGhost(frame.displayedUnit) then
82         return;
83     end
84
85     local name, icon, count, debuff, expires, caster, id;
86     local current = GetTime();
87     for _, filter in ipairs(auraFilters) do
88         local i = 1;
89         while true do
90             name, _, icon, count, debuff, _, expires, caster, _, _, id = UnitAura(unit, i, filter);
91             if not id then break end
92             local pos = watchedAuras[name] or watchedAuras[id] or watchedAuras[debuff];
93             if pos then
94                 local ind = f[frameName][pos];
95                 local config = OmaRF.db.profile.indicators[pos];
96                 if not config.mine or UnitIsPlayer(caster) then
97                     if config.showIcon then
98                         -- show icon
99                         if config.useDefaultIcon then
100                             ind.icon:SetTexture(DEFAULT_ICON);
101                         else
102                             ind.icon:SetTexture(icon);
103                         end
104                     end
105                     if config.showText then
106                         -- show text
107                         local text;
108                         local remaining = expires - current;
109                         if remaining > 60 then
110                             text = format("%dm", ceil(remaining/60));
111                         else
112                             text = format("%d", floor(remaining+0.5));
113                         end
114                         if count > 1 and config.stack then
115                             if text then
116                                 text = count.."-"..text;
117                             else
118                                 text = count;
119                             end
120                         end
121
122                         ind.text:SetText(text);
123                     end
124                 end
125             end
126             i = i + 1;
127         end
128     end
129 end
130
131 -- Update all indicators
132 function OmaRF:UpdateAllIndicators()
133     CompactRaidFrameContainer_ApplyToFrames(CompactRaidFrameContainer, "normal", updateIndicators);
134     if OmaRF.running then
135         C_TimerAfter(0.15, OmaRF.UpdateAllIndicators);
136     end
137 end
138
139 -- Used to update everything that is affected by the configuration
140 function OmaRF:RefreshConfig()
141     self:OnDisable(); -- clear everything
142     if self.db.profile.enabled then
143         CompactRaidFrameContainer_ApplyToFrames(CompactRaidFrameContainer, "normal", configureIndicators);
144         -- Format aura strings
145         watchedAuras = {};
146         for _, pos in ipairs(positions) do
147             for _, aura in ipairs(self.db.profile.indicators[pos]["auras"]) do
148                 watchedAuras[aura] = pos; -- TODO single aura only in one position
149             end
150         end
151
152         if next(watchedAuras) ~= nil then
153             self.running = true;
154             C_TimerAfter(0.15, self.UpdateAllIndicators);
155         end
156     end
157 end