c0c06ef - Add basic action bar support
authorAleksi Blinnikka <aleksi.blinnikka@gmail.com>
Tue, 6 Feb 2018 02:14:12 +0000
committerAleksi Blinnikka <aleksi.blinnikka@gmail.com>
Tue, 6 Feb 2018 02:14:12 +0000
OmaAB/ActionBars.lua [new file with mode: 0644]
OmaAB/OmaAB.toc

diff --git a/OmaAB/ActionBars.lua b/OmaAB/ActionBars.lua
new file mode 100644 (file)
index 0000000..e3460ed
--- /dev/null
@@ -0,0 +1,340 @@
+-- ActionBars.lua
+local _;
+local pairs = pairs;
+local GetActionTexture = GetActionTexture;
+local GetActionLossOfControlCooldown = GetActionLossOfControlCooldown;
+local GetActionCooldown, GetActionCharges = GetActionCooldown, GetActionCharges;
+local IsConsumableAction, IsStackableAction = IsConsumableAction, IsStackableAction;
+local IsItemAction, GetActionCount = IsItemAction, GetActionCount;
+local CooldownFrame_Set, CooldownFrame_Clear = CooldownFrame_Set, CooldownFrame_Clear;
+local GameTooltip = nil;
+local COOLDOWN_TYPE_LOSS_OF_CONTROL = COOLDOWN_TYPE_LOSS_OF_CONTROL;
+local COOLDOWN_TYPE_NORMAL = COOLDOWN_TYPE_NORMAL;
+local CDTexture = "Interface\\Cooldown\\edge";
+local locCDTexture = "Interface\\Cooldown\\edge-LoC";
+
+local BUTTONLOCK = false; -- change to lock button dragging
+
+local settings = {
+    ["OmaBT1"] = {
+        start = 1,
+        length = 12,
+        x = 1000,
+        y = 1000,
+    },
+    ["OmaBT2"] = {
+        start = 13,
+        length = 12,
+        x = 1000,
+        y = 960,
+    },
+    ["OmaBT3"] = {
+        start = 25,
+        length = 12,
+        x = 1000,
+        y = 920,
+    },
+    ["OmaBT4"] = {
+        start = 37,
+        length = 12,
+        x = 1000,
+        y = 880,
+    },
+    ["OmaBT5"] = {
+        start = 49,
+        length = 12,
+        x = 1000,
+        y = 840,
+    },
+    ["OmaBT6"] = {
+        start = 61,
+        length = 12,
+        x = 1000,
+        y = 800,
+    },
+    -- bogus data past this
+    --["OmaBT7"] = {
+    --    start = 73,
+    --    length = 12,
+    --    x = 1000,
+    --    y = 760,
+    --},
+    --["OmaBT8"] = {
+    --    start = 85,
+    --    length = 12,
+    --    x = 1000,
+    --    y = 760,
+    --},
+    --["OmaBT9"] = {
+    --    start = 97,
+    --    length = 12,
+    --    x = 1000,
+    --    y = 760,
+    --},
+    --["OmaBT10"] = {
+    --    start = 109,
+    --    length = 12,
+    --    x = 1000,
+    --    y = 760,
+    --},
+};
+
+local buttons = {};
+
+local ActionBars = CreateFrame("Frame", "OmaActionBars", UIParent);
+local inheritedFrames = "SecureActionButtonTemplate,SecureHandlerDragTemplate";
+
+local numChargeCDs = 0;
+local function createChargeCD(parent)
+    numChargeCDs = numChargeCDs + 1;
+    local frame = CreateFrame("Cooldown", "OmaChargeCD"..numChargeCDs, parent, "CooldownFrameTemplate");
+    frame:SetHideCountdownNumbers(false);
+    frame:SetDrawSwipe(false);
+    frame:SetAllPoints(parent);
+    frame:SetFrameStrata("TOOLTIP");
+    return frame;
+end
+
+local function clearChargeCD(parent)
+    if parent.chargecd then CooldownFrame_Clear(parent.chargecd) end
+end
+
+local function startChargeCD(parent, start, duration, modrate)
+    if start == 0 then
+        return clearChargeCD(parent);
+    end
+    parent.chargecd = parent.chargecd or createChargeCD(parent);
+    CooldownFrame_Set(parent.chargecd, start, duration, true, true, modrate);
+end
+
+local redoCooldown;
+
+local function updateCooldown(button, slot)
+    -- CD update from FrameXML/ActionButton.lua
+    -- TODO charges
+    local locstart, locduration = GetActionLossOfControlCooldown(slot);
+    local start, duration, enable, modrate = GetActionCooldown(slot);
+    local charges, maxcharges, chargestart, chargeduration, chargemodrate = GetActionCharges(slot);
+    if (locstart + locduration) > (start + duration) then
+        if button.cd.currentCooldownType ~= COOLDOWN_TYPE_LOSS_OF_CONTROL then
+            button.cd:SetEdgeTexture(locCDTexture);
+            button.cd:SetSwipeColor(0.17, 0, 0);
+            button.cd:SetHideCountdownNumbers(true);
+            button.cd.currentCooldownType = COOLDOWN_TYPE_LOSS_OF_CONTROL;
+        end
+
+        CooldownFrame_Set(button.cd, locstart, locduration, true, true, modrate);
+        clearChargeCD(button);
+    else
+        if button.cd.currentCooldownType ~= COOLDOWN_TYPE_NORMAL then
+            button.cd:SetEdgeTexture(CDTexture);
+            button.cd:SetSwipeColor(0, 0, 0);
+            button.cd:SetHideCountdownNumbers(false);
+            button.cd.currentCooldownType = COOLDOWN_TYPE_NORMAL;
+        end
+
+        if locstart > 0 then
+            button.cd:SetScript("OnCooldownDone", redoCooldown);
+        end
+        if charges and maxcharges and maxcharges > 1 and charges < maxcharges then
+            startChargeCD(button, chargestart, chargeduration, chargemodrate);
+        else
+            clearChargeCD(button);
+        end
+        CooldownFrame_Set(button.cd, start, duration, enable, false, modrate);
+    end
+end
+
+local function redoCooldown(cd)
+    local button = cd:GetParent();
+    cd:SetScript("OnCooldownDone", nil);
+    updateCooldown(button, button.slot);
+end
+
+local function updateCount(button, slot)
+    if IsConsumableAction(slot) or IsStackableAction(slot) or
+            (not IsItemAction(slot) and GetActionCount(slot) > 0) then
+        local count = GetActionCount(slot);
+        if count > 99 then
+            button.count:SetText("*");
+        else
+            button.count:SetText(count);
+        end
+    else
+        local charges, maxcharges = GetActionCharges(slot);
+        if maxcharges > 1 then
+            button.count:SetText(charges);
+        else
+            button.count:SetText("");
+        end
+    end
+end
+
+local function updateButton(button, slot)
+    local texture = GetActionTexture(slot);
+    if texture then
+        button.hasaction = true;
+        button.base:Show();
+        button.icon:SetTexture(texture);
+        updateCount(button, slot);
+        updateCooldown(button, slot);
+    else
+        button.hasaction = nil;
+        if not button.grid then button.base:Hide() end
+        button.icon:SetTexture(nil);
+    end
+end
+
+local function createActionBar(parent, name, config)
+    local prev;
+    for slot = config.start, config.start+config.length-1 do
+        local secure = CreateFrame("Button", name..slot, parent, inheritedFrames);
+        secure.slot = slot;
+        if slot == config.start then
+            secure:SetPoint("TOPLEFT", parent, "BOTTOMLEFT", config.x, config.y);
+        else
+            secure:SetPoint("TOPLEFT", prev, "TOPRIGHT");
+        end
+        secure:RegisterForClicks("AnyUp");
+        if not BUTTONLOCK then
+            secure:RegisterForDrag("LeftButton", "RightButton");
+        end
+        secure:SetWidth(32);
+        secure:SetHeight(32);
+        secure.base = secure:CreateTexture(nil, "BACKGROUND");
+        secure.base:SetAllPoints();
+        secure.base:SetColorTexture(0, 0, 0, 0.5);
+        secure.iconbase = secure:CreateTexture(nil, "BORDER");
+        secure.iconbase:SetPoint("TOPLEFT", secure.base, "TOPLEFT", 1, -1);
+        secure.iconbase:SetPoint("BOTTOMRIGHT", secure.base, "BOTTOMRIGHT", -1, 1);
+        secure.iconbase:SetColorTexture(0, 0, 0, 0.5);
+        secure.iconbase:Hide();
+        secure.icon = secure:CreateTexture(nil, "ARTWORK");
+        secure.icon:SetPoint("TOPLEFT", secure.iconbase, "TOPLEFT");
+        secure.icon:SetPoint("BOTTOMRIGHT", secure.iconbase, "BOTTOMRIGHT");
+        secure.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93);
+        secure.hotkey = secure:CreateFontString(nil, "OVERLAY", "NumberFontNormalGray");
+        secure.hotkey:SetPoint("TOPRIGHT", secure, "TOPRIGHT", 2, -1);
+        secure.count = secure:CreateFontString(nil, "OVERLAY", "NumberFontNormal");
+        secure.count:SetPoint("BOTTOMRIGHT", secure, "BOTTOMRIGHT", 2, -1);
+        secure.cd = CreateFrame("Cooldown", name..slot.."CD", secure, "CooldownFrameTemplate");
+        secure.cd:SetAllPoints();
+        secure:SetAttribute("type", "action");
+        secure:SetAttribute("action", slot);
+        function secure:ActionChanged()
+            return updateButton(self, slot);
+        end
+        secure:ActionChanged(); -- initial update
+        -- FrameXML/SecureHandlers.lua has arguments and return value
+        -- args: self, button, kind, value, ... (kind, value, ... from GetCursorInfo())
+        -- returns: kind, target, detail
+        -- or: "clear", kind, target, detail
+        -- used for Pickup* functions
+        -- some of these snippets based on LibActionButton-1.0
+        secure:SetAttribute("_ondragstart", [=[
+            return "action", self:GetAttribute("action");
+        ]=]);
+        secure:SetAttribute("_onreceivedrag", [=[
+            if not kind or not value then return nil end
+            return "action", self:GetAttribute("action");
+        ]=]);
+        -- pre-wrapper can pass a message to post-wrapper
+        secure:WrapScript(secure, "OnDragStart", [=[
+            local kind, value = GetActionInfo(self:GetAttribute("action"));
+            return "message", format("%s|%s", tostring(kind), tostring(value));
+        ]=], [=[
+            local kind, value = GetActionInfo(self:GetAttribute("action"));
+            if message ~= format("%s|%s", tostring(kind), tostring(value)) then
+                self:CallMethod("ActionChanged");
+            end
+        ]=]);
+        secure:WrapScript(secure, "OnReceiveDrag", [=[
+            local kind, value = GetActionInfo(self:GetAttribute("action"));
+            return "message", format("%s|%s", tostring(kind), tostring(value));
+        ]=], [=[
+            local kind, value = GetActionInfo(self:GetAttribute("action"));
+            if message ~= format("%s|%s", tostring(kind), tostring(value)) then
+                self:CallMethod("ActionChanged");
+            end
+        ]=]);
+        secure:WrapScript(secure, "OnClick", [=[
+            local kind, value = GetActionInfo(self:GetAttribute("action"));
+            return nil, format("%s|%s", tostring(kind), tostring(value));
+        ]=], [=[
+            local kind, value = GetActionInfo(self:GetAttribute("action"));
+            if message ~= format("%s|%s", tostring(kind), tostring(value)) then
+                self:CallMethod("ActionChanged");
+            end
+        ]=]);
+        buttons[slot] = secure;
+        prev = secure;
+    end
+end
+
+local function initialize()
+    ActionBars:SetFrameStrata("LOW");
+    ActionBars:SetPoint("BOTTOMLEFT");
+    ActionBars:SetWidth(1);
+    ActionBars:SetHeight(1);
+    for name, config in pairs(settings) do
+        createActionBar(ActionBars, name, config);
+    end
+end
+
+local events = {
+    ["ACTIONBAR_UPDATE_COOLDOWN"] = function()
+        for _, button in pairs(buttons) do
+            updateCooldown(button, button.slot);
+        end
+    end,
+    ["SPELL_UPDATE_CHARGES"] = function()
+        for _, button in pairs(buttons) do
+            updateCount(button, button.slot);
+        end
+    end,
+    ["ACTIONBAR_SLOT_CHANGED"] = function(slot)
+        if buttons[slot] then buttons[slot]:ActionChanged() end
+    end,
+    ["ACTIONBAR_SHOWGRID"] = function()
+        for _, button in pairs(buttons) do
+            button.grid = true;
+            button.iconbase:Show();
+            if not button.hasaction then button.base:Show() end
+        end
+    end,
+    ["ACTIONBAR_HIDEGRID"] = function()
+        for _, button in pairs(buttons) do
+            button.grid = nil;
+            button.iconbase:Hide();
+            if not button.hasaction then button.base:Hide() end
+        end
+    end,
+    ["UPDATE_ALL_BUTTONS"] = function()
+        for _, button in pairs(buttons) do
+            updateButton(button, button.slot);
+        end
+    end,
+    ["UPDATE_BINDINGS"] = function()
+    end,
+    ["PLAYER_LOGIN"] = function()
+        GameTooltip = _G["GameTooltip"];
+        initialize();
+    end,
+};
+events["LOSS_OF_CONTROL_ADDED"] = events["ACTIONBAR_UPDATE_COOLDOWN"];
+events["LOSS_OF_CONTROL_UPDATE"] = events["ACTIONBAR_UPDATE_COOLDOWN"]; -- TODO might change once tooltips are in
+events["SPELL_UPDATE_ICON"] = events["UPDATE_ALL_BUTTONS"];
+events["PET_STABLE_UPDATE"] = events["UPDATE_ALL_BUTTONS"];
+events["PET_STABLE_SHOW"] = events["UPDATE_ALL_BUTTONS"];
+-- TODO overlay glow ? don't exactly know what it does
+-- autorepeat, tooltips
+
+ActionBars:RegisterEvent("PLAYER_LOGIN");
+ActionBars:RegisterEvent("ACTIONBAR_UPDATE_COOLDOWN");
+ActionBars:RegisterEvent("SPELL_UPDATE_CHARGES");
+ActionBars:RegisterEvent("ACTIONBAR_SLOT_CHANGED");
+ActionBars:RegisterEvent("ACTIONBAR_SHOWGRID");
+ActionBars:RegisterEvent("ACTIONBAR_HIDEGRID");
+ActionBars:SetScript("OnEvent", function(self, event, arg1)
+    events[event](arg1);
+end);
index b5c13b4..2ee57ec 100644 (file)
@@ -6,3 +6,4 @@
 
 ExpBar.lua
 TellMeWhen.lua
+ActionBars.lua