c6843f3 - Refactor updateIndicators to get auras when they're applied
[wowui.git] / OmaRF / Indicators.lua
index ebece6c..9557258 100644 (file)
@@ -1,5 +1,5 @@
-local media = LibStub:GetLibrary("LibSharedMedia-3.0");
 local f = OmaRF.frames;
 local f = OmaRF.frames;
+local majorFrames = OmaRF.majorFrames;
 local positions = OmaRF.positions;
 local pad = 2;
 local paddings = {
 local positions = OmaRF.positions;
 local pad = 2;
 local paddings = {
@@ -9,7 +9,9 @@ local paddings = {
     BOTTOMLEFT = {pad, pad},
     BOTTOMRIGHT = {-pad, pad}
 };
     BOTTOMLEFT = {pad, pad},
     BOTTOMRIGHT = {-pad, pad}
 };
-local watchedAuras; -- all watched auras
+local watchedAuras;
+local majorAuras;
+local majorMax;
 local auraFilters = {"HELPFUL", "HARMFUL"};
 local DEFAULT_ICON = "Interface\\AddOns\\OmaRF\\images\\rhomb";
 local _;
 local auraFilters = {"HELPFUL", "HARMFUL"};
 local DEFAULT_ICON = "Interface\\AddOns\\OmaRF\\images\\rhomb";
 local _;
@@ -22,30 +24,79 @@ local UnitIsPlayer = UnitIsPlayer;
 local UnitIsConnected = UnitIsConnected;
 local UnitIsDeadOrGhost = UnitIsDeadOrGhost;
 local CompactRaidFrameContainer_ApplyToFrames = CompactRaidFrameContainer_ApplyToFrames;
 local UnitIsConnected = UnitIsConnected;
 local UnitIsDeadOrGhost = UnitIsDeadOrGhost;
 local CompactRaidFrameContainer_ApplyToFrames = CompactRaidFrameContainer_ApplyToFrames;
+local format = string.format;
+local unpack = unpack;
+local floor = floor;
+local ceil = ceil;
 
 
--- list of important auras TODO try to use spellIDs
-local centerAuras = {
-    "Power Word: Shield"
-};
+-- update current auras
+hooksecurefunc("CompactUnitFrame_UpdateAuras", function(frame)
+    local frameName = frame:GetName();
+    if f[frameName] then
+        for _, ind in pairs(f[frameName]) do ind.expires = nil end
+        for _, ind in ipairs(majorFrames[frameName]) do ind.expires = nil end
+
+        local name, icon, count, expires, caster, id;
+        local unit = frame.displayedUnit;
+        local majorI = 1;
+        for _, filter in ipairs(auraFilters) do
+            local i = 1;
+            while true do
+                name, _, icon, count, _, _, expires, caster, _, _, id = UnitAura(unit, i, filter);
+                if not id then break end
+                local pos = watchedAuras[id] or watchedAuras[name];
+                if pos then
+                    local ind = f[frameName][pos];
+                    local config = OmaRF.db.profile.indicators[pos];
+                    if not config.mine or UnitIsPlayer(caster) then
+                        if config.useDefaultIcon then
+                            ind.icon:SetTexture(DEFAULT_ICON);
+                        else
+                            ind.icon:SetTexture(icon);
+                        end
+                        ind.expires = expires;
+                    end
+                end
+
+                if (majorAuras[id] or majorAuras[name]) and majorI <= majorMax then
+                    local ind = majorFrames[frameName][majorI];
+                    ind.icon:SetTexture(icon);
+                    ind.expires = expires;
+                    if count > 1 then
+                        ind.stackText:SetText(count);
+                    end
+                    majorI = majorI + 1;
+                end
+                i = i + 1;
+            end
+        end
+    end
+end);
 
 local function configureIndicators(frame, name)
     local frameName = name or frame:GetName();
     if not f[frameName] then return end
 
     local config = OmaRF.db.profile.indicators;
 
 local function configureIndicators(frame, name)
     local frameName = name or frame:GetName();
     if not f[frameName] then return end
 
     local config = OmaRF.db.profile.indicators;
-    local font = media and media:Fetch('font', config.indicatorFont) or STANDARD_TEXT_FONT;
     for pos, ind in pairs(f[frameName]) do
     for pos, ind in pairs(f[frameName]) do
-        ind.text:SetFont(font, config[pos]["textSize"]);
+        ind.text:SetFont(STANDARD_TEXT_FONT, config[pos]["textSize"]);
         ind.text:SetTextColor(unpack(config[pos]["textColor"]));
         ind.icon:SetWidth(config[pos]["iconSize"]);
         ind.icon:SetHeight(config[pos]["iconSize"]);
         ind.icon:SetTexture(DEFAULT_ICON);
         ind.icon:SetVertexColor(unpack(config[pos]["iconColor"]));
         ind.text:SetTextColor(unpack(config[pos]["textColor"]));
         ind.icon:SetWidth(config[pos]["iconSize"]);
         ind.icon:SetHeight(config[pos]["iconSize"]);
         ind.icon:SetTexture(DEFAULT_ICON);
         ind.icon:SetVertexColor(unpack(config[pos]["iconColor"]));
-        if config[pos]["showIcon"] then
-            ind.icon:Show();
-        else
-            ind.icon:Hide();
+    end
+
+    config = OmaRF.db.profile.majorAuras;
+    for i, ind in ipairs(majorFrames[frameName]) do
+        if i == 1 then
+            ind.icon:ClearAllPoints();
+            ind.icon:SetPoint("CENTER", frame, "CENTER", -config.iconSize, 0);
         end
         end
+        ind.icon:SetWidth(config.iconSize);
+        ind.icon:SetHeight(config.iconSize);
+        ind.expireText:SetFont(STANDARD_TEXT_FONT, config["textSize"], "OUTLINE");
+        ind.stackText:SetFont(STANDARD_TEXT_FONT, config["textSize"], "OUTLINE");
     end
 end
 
     end
 end
 
@@ -59,69 +110,91 @@ local function setupCompactUnitFrame(frame, name)
         f[name][pos].icon = frame:CreateTexture(nil, "OVERLAY");
         f[name][pos].icon:SetPoint(pos, frame, pos, paddings[pos][1], paddings[pos][2]);
     end
         f[name][pos].icon = frame:CreateTexture(nil, "OVERLAY");
         f[name][pos].icon:SetPoint(pos, frame, pos, paddings[pos][1], paddings[pos][2]);
     end
+
+    local config = OmaRF.db.profile.majorAuras;
+    majorFrames[name] = {};
+    for i = 1, config.max do
+        majorFrames[name][i] = {};
+        majorFrames[name][i].icon = frame:CreateTexture(nil, "OVERLAY");
+        if i > 1 then
+            majorFrames[name][i].icon:SetPoint("TOPLEFT", majorFrames[name][i-1].icon, "TOPRIGHT");
+        end
+        majorFrames[name][i].expireText = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall");
+        majorFrames[name][i].expireText:SetPoint("BOTTOMRIGHT", majorFrames[name][i].icon, "BOTTOMRIGHT");
+        majorFrames[name][i].stackText = frame:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall");
+        majorFrames[name][i].stackText:SetPoint("TOPLEFT", majorFrames[name][i].icon, "TOPLEFT");
+    end
+
     configureIndicators(frame, name);
 end
 
     configureIndicators(frame, name);
 end
 
+local function remaining(expires, current)
+    if expires == 0 then return "" end
+    local remain = expires - current;
+    if remain > 60 then
+        return format("%dm", ceil(remain/60));
+    end
+    return floor(remain+0.5);
+end
+
+local function hide(frameName)
+    for _, ind in pairs(f[frameName]) do
+        ind.text:Hide();
+        ind.icon:Hide();
+    end
+    for _, ind in ipairs(majorFrames[frameName]) do
+        ind.icon:Hide();
+        ind.expireText:Hide();
+        ind.stackText:Hide();
+    end
+end
+
 -- Check the indicators on a frame and update the times on them
 local function updateIndicators(frame)
     local frameName = frame:GetName();
     local unit = frame.unit;
     if not unit then return end -- possible if the frame is just being hidden
 
 -- Check the indicators on a frame and update the times on them
 local function updateIndicators(frame)
     local frameName = frame:GetName();
     local unit = frame.unit;
     if not unit then return end -- possible if the frame is just being hidden
 
-    -- Create indicators if needed
-    if not f[frameName] then setupCompactUnitFrame(frame, frameName) end
-    -- Reset current
-    for _, ind in pairs(f[frameName]) do
-        ind.text:SetText("");
-        ind.icon:SetTexture("");
+    -- Create indicators if needed, out of combat if forbidden
+    if not f[frameName] then
+        if frame:IsForbidden() then
+            if not OmaRF.ooc_queue[frameName] then
+                OmaRF.ooc_queue[frameName] = {
+                    func = setupCompactUnitFrame,
+                    args = { frame, frameName }
+                };
+            end
+            return;
+        else
+            setupCompactUnitFrame(frame, frameName);
+        end
     end
     end
+    -- Reset current
+    hide(frameName);
     -- Hide if unit is dead/disconnected
     if (not UnitIsConnected(unit)) or UnitIsDeadOrGhost(frame.displayedUnit) then
         return;
     end
 
     -- Hide if unit is dead/disconnected
     if (not UnitIsConnected(unit)) or UnitIsDeadOrGhost(frame.displayedUnit) then
         return;
     end
 
-    local name, icon, count, debuff, expires, caster, id;
     local current = GetTime();
     local current = GetTime();
-    for _, filter in ipairs(auraFilters) do
-        local i = 1;
-        while true do
-            name, _, icon, count, debuff, _, expires, caster, _, _, id = UnitAura(unit, i, filter);
-            if not id then break end
-            local pos = watchedAuras[name] or watchedAuras[id] or watchedAuras[debuff];
-            if pos then
-                local ind = f[frameName][pos];
-                local config = OmaRF.db.profile.indicators[pos];
-                if not config.mine or UnitIsPlayer(caster) then
-                    if config.showIcon then
-                        -- show icon
-                        if config.useDefaultIcon then
-                            ind.icon:SetTexture(DEFAULT_ICON);
-                        else
-                            ind.icon:SetTexture(icon);
-                        end
-                    end
-                    if config.showText then
-                        -- show text
-                        local text;
-                        local remaining = expires - current;
-                        if remaining > 60 then
-                            text = string.format("%dm", ceil(remaining/60));
-                        else
-                            text = string.format("%d", floor(remaining+0.5));
-                        end
-                        if count > 1 and config.stack then
-                            if text then
-                                text = count.."-"..text;
-                            else
-                                text = count;
-                            end
-                        end
-
-                        ind.text:SetText(text);
-                    end
-                end
+    for pos, ind in pairs(f[frameName]) do
+        if ind.expires ~= nil then
+            local config = OmaRF.db.profile.indicators[pos];
+            if config.showIcon then
+                ind.icon:Show();
+            end
+            if config.showText then
+                ind.text:SetText(remaining(ind.expires, current));
+                ind.text:Show();
             end
             end
-            i = i + 1;
+        end
+    end
+    for _, ind in ipairs(majorFrames[frameName]) do
+        if ind.expires ~= nil then
+            ind.icon:Show();
+            ind.expireText:SetText(remaining(ind.expires, current));
+            ind.expireText:Show();
+            ind.stackText:Show();
         end
     end
 end
         end
     end
 end
@@ -139,15 +212,19 @@ function OmaRF:RefreshConfig()
     self:OnDisable(); -- clear everything
     if self.db.profile.enabled then
         CompactRaidFrameContainer_ApplyToFrames(CompactRaidFrameContainer, "normal", configureIndicators);
     self:OnDisable(); -- clear everything
     if self.db.profile.enabled then
         CompactRaidFrameContainer_ApplyToFrames(CompactRaidFrameContainer, "normal", configureIndicators);
-        -- Format aura strings
         watchedAuras = {};
         for _, pos in ipairs(positions) do
             for _, aura in ipairs(self.db.profile.indicators[pos]["auras"]) do
                 watchedAuras[aura] = pos; -- TODO single aura only in one position
             end
         end
         watchedAuras = {};
         for _, pos in ipairs(positions) do
             for _, aura in ipairs(self.db.profile.indicators[pos]["auras"]) do
                 watchedAuras[aura] = pos; -- TODO single aura only in one position
             end
         end
+        majorAuras = {};
+        for _, aura in ipairs(self.db.profile.majorAuras["auras"]) do
+            majorAuras[aura] = true;
+        end
+        majorMax = OmaRF.db.profile.majorAuras["max"];
 
 
-        if next(watchedAuras) ~= nil then
+        if next(watchedAuras) ~= nil or next(majorAuras) ~= nil then
             self.running = true;
             C_TimerAfter(0.15, self.UpdateAllIndicators);
         end
             self.running = true;
             C_TimerAfter(0.15, self.UpdateAllIndicators);
         end