4 local GetActionTexture = GetActionTexture;
5 local GetActionLossOfControlCooldown = GetActionLossOfControlCooldown;
6 local GetActionCooldown, GetActionCharges = GetActionCooldown, GetActionCharges;
7 local IsConsumableAction, IsStackableAction = IsConsumableAction, IsStackableAction;
8 local IsItemAction, GetActionCount = IsItemAction, GetActionCount;
9 local CooldownFrame_Set, CooldownFrame_Clear = CooldownFrame_Set, CooldownFrame_Clear;
10 local GameTooltip = nil;
11 local COOLDOWN_TYPE_LOSS_OF_CONTROL = COOLDOWN_TYPE_LOSS_OF_CONTROL;
12 local COOLDOWN_TYPE_NORMAL = COOLDOWN_TYPE_NORMAL;
13 local CDTexture = "Interface\\Cooldown\\edge";
14 local locCDTexture = "Interface\\Cooldown\\edge-LoC";
16 local BUTTONLOCK = false; -- change to lock button dragging
55 -- bogus data past this
84 local ActionBars = CreateFrame("Frame", "OmaActionBars", UIParent);
85 local inheritedFrames = "SecureActionButtonTemplate,SecureHandlerDragTemplate";
87 local numChargeCDs = 0;
88 local function createChargeCD(parent)
89 numChargeCDs = numChargeCDs + 1;
90 local frame = CreateFrame("Cooldown", "OmaChargeCD"..numChargeCDs, parent, "CooldownFrameTemplate");
91 frame:SetHideCountdownNumbers(false);
92 frame:SetDrawSwipe(false);
93 frame:SetAllPoints(parent);
94 frame:SetFrameStrata("TOOLTIP");
98 local function clearChargeCD(parent)
99 if parent.chargecd then CooldownFrame_Clear(parent.chargecd) end
102 local function startChargeCD(parent, start, duration, modrate)
104 return clearChargeCD(parent);
106 parent.chargecd = parent.chargecd or createChargeCD(parent);
107 CooldownFrame_Set(parent.chargecd, start, duration, true, true, modrate);
112 local function updateCooldown(button, slot)
113 -- CD update from FrameXML/ActionButton.lua
115 local locstart, locduration = GetActionLossOfControlCooldown(slot);
116 local start, duration, enable, modrate = GetActionCooldown(slot);
117 local charges, maxcharges, chargestart, chargeduration, chargemodrate = GetActionCharges(slot);
118 if (locstart + locduration) > (start + duration) then
119 if button.cd.currentCooldownType ~= COOLDOWN_TYPE_LOSS_OF_CONTROL then
120 button.cd:SetEdgeTexture(locCDTexture);
121 button.cd:SetSwipeColor(0.17, 0, 0);
122 button.cd:SetHideCountdownNumbers(true);
123 button.cd.currentCooldownType = COOLDOWN_TYPE_LOSS_OF_CONTROL;
126 CooldownFrame_Set(button.cd, locstart, locduration, true, true, modrate);
127 clearChargeCD(button);
129 if button.cd.currentCooldownType ~= COOLDOWN_TYPE_NORMAL then
130 button.cd:SetEdgeTexture(CDTexture);
131 button.cd:SetSwipeColor(0, 0, 0);
132 button.cd:SetHideCountdownNumbers(false);
133 button.cd.currentCooldownType = COOLDOWN_TYPE_NORMAL;
137 button.cd:SetScript("OnCooldownDone", redoCooldown);
139 if charges and maxcharges and maxcharges > 1 and charges < maxcharges then
140 startChargeCD(button, chargestart, chargeduration, chargemodrate);
142 clearChargeCD(button);
144 CooldownFrame_Set(button.cd, start, duration, enable, false, modrate);
148 local function redoCooldown(cd)
149 local button = cd:GetParent();
150 cd:SetScript("OnCooldownDone", nil);
151 updateCooldown(button, button.slot);
154 local function updateCount(button, slot)
155 if IsConsumableAction(slot) or IsStackableAction(slot) or
156 (not IsItemAction(slot) and GetActionCount(slot) > 0) then
157 local count = GetActionCount(slot);
159 button.count:SetText("*");
161 button.count:SetText(count);
164 local charges, maxcharges = GetActionCharges(slot);
165 if maxcharges > 1 then
166 button.count:SetText(charges);
168 button.count:SetText("");
173 local function updateButton(button, slot)
174 local texture = GetActionTexture(slot);
176 button.hasaction = true;
178 button.icon:SetTexture(texture);
179 updateCount(button, slot);
180 updateCooldown(button, slot);
182 button.hasaction = nil;
183 if not button.grid then button.base:Hide() end
184 button.icon:SetTexture(nil);
188 local function createActionBar(parent, name, config)
190 for slot = config.start, config.start+config.length-1 do
191 local secure = CreateFrame("Button", name..slot, parent, inheritedFrames);
193 if slot == config.start then
194 secure:SetPoint("TOPLEFT", parent, "BOTTOMLEFT", config.x, config.y);
196 secure:SetPoint("TOPLEFT", prev, "TOPRIGHT");
198 secure:RegisterForClicks("AnyUp");
199 if not BUTTONLOCK then
200 secure:RegisterForDrag("LeftButton", "RightButton");
203 secure:SetHeight(32);
204 secure.base = secure:CreateTexture(nil, "BACKGROUND");
205 secure.base:SetAllPoints();
206 secure.base:SetColorTexture(0, 0, 0, 0.5);
207 secure.iconbase = secure:CreateTexture(nil, "BORDER");
208 secure.iconbase:SetPoint("TOPLEFT", secure.base, "TOPLEFT", 1, -1);
209 secure.iconbase:SetPoint("BOTTOMRIGHT", secure.base, "BOTTOMRIGHT", -1, 1);
210 secure.iconbase:SetColorTexture(0, 0, 0, 0.5);
211 secure.iconbase:Hide();
212 secure.icon = secure:CreateTexture(nil, "ARTWORK");
213 secure.icon:SetPoint("TOPLEFT", secure.iconbase, "TOPLEFT");
214 secure.icon:SetPoint("BOTTOMRIGHT", secure.iconbase, "BOTTOMRIGHT");
215 secure.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93);
216 secure.hotkey = secure:CreateFontString(nil, "OVERLAY", "NumberFontNormalGray");
217 secure.hotkey:SetPoint("TOPRIGHT", secure, "TOPRIGHT", 2, -1);
218 secure.count = secure:CreateFontString(nil, "OVERLAY", "NumberFontNormal");
219 secure.count:SetPoint("BOTTOMRIGHT", secure, "BOTTOMRIGHT", 2, -1);
220 secure.cd = CreateFrame("Cooldown", name..slot.."CD", secure, "CooldownFrameTemplate");
221 secure.cd:SetAllPoints();
222 secure:SetAttribute("type", "action");
223 secure:SetAttribute("action", slot);
224 function secure:ActionChanged()
225 return updateButton(self, slot);
227 secure:ActionChanged(); -- initial update
228 -- FrameXML/SecureHandlers.lua has arguments and return value
229 -- args: self, button, kind, value, ... (kind, value, ... from GetCursorInfo())
230 -- returns: kind, target, detail
231 -- or: "clear", kind, target, detail
232 -- used for Pickup* functions
233 -- some of these snippets based on LibActionButton-1.0
234 secure:SetAttribute("_ondragstart", [=[
235 return "action", self:GetAttribute("action");
237 secure:SetAttribute("_onreceivedrag", [=[
238 if not kind or not value then return nil end
239 return "action", self:GetAttribute("action");
241 -- pre-wrapper can pass a message to post-wrapper
242 secure:WrapScript(secure, "OnDragStart", [=[
243 local kind, value = GetActionInfo(self:GetAttribute("action"));
244 return "message", format("%s|%s", tostring(kind), tostring(value));
246 local kind, value = GetActionInfo(self:GetAttribute("action"));
247 if message ~= format("%s|%s", tostring(kind), tostring(value)) then
248 self:CallMethod("ActionChanged");
251 secure:WrapScript(secure, "OnReceiveDrag", [=[
252 local kind, value = GetActionInfo(self:GetAttribute("action"));
253 return "message", format("%s|%s", tostring(kind), tostring(value));
255 local kind, value = GetActionInfo(self:GetAttribute("action"));
256 if message ~= format("%s|%s", tostring(kind), tostring(value)) then
257 self:CallMethod("ActionChanged");
260 secure:WrapScript(secure, "OnClick", [=[
261 local kind, value = GetActionInfo(self:GetAttribute("action"));
262 return nil, format("%s|%s", tostring(kind), tostring(value));
264 local kind, value = GetActionInfo(self:GetAttribute("action"));
265 if message ~= format("%s|%s", tostring(kind), tostring(value)) then
266 self:CallMethod("ActionChanged");
269 buttons[slot] = secure;
274 local function initialize()
275 ActionBars:SetFrameStrata("LOW");
276 ActionBars:SetPoint("BOTTOMLEFT");
277 ActionBars:SetWidth(1);
278 ActionBars:SetHeight(1);
279 for name, config in pairs(settings) do
280 createActionBar(ActionBars, name, config);
285 ["ACTIONBAR_UPDATE_COOLDOWN"] = function()
286 for _, button in pairs(buttons) do
287 updateCooldown(button, button.slot);
290 ["SPELL_UPDATE_CHARGES"] = function()
291 for _, button in pairs(buttons) do
292 updateCount(button, button.slot);
295 ["ACTIONBAR_SLOT_CHANGED"] = function(slot)
296 if buttons[slot] then buttons[slot]:ActionChanged() end
298 ["ACTIONBAR_SHOWGRID"] = function()
299 for _, button in pairs(buttons) do
301 button.iconbase:Show();
302 if not button.hasaction then button.base:Show() end
305 ["ACTIONBAR_HIDEGRID"] = function()
306 for _, button in pairs(buttons) do
308 button.iconbase:Hide();
309 if not button.hasaction then button.base:Hide() end
312 ["UPDATE_ALL_BUTTONS"] = function()
313 for _, button in pairs(buttons) do
314 updateButton(button, button.slot);
317 ["UPDATE_BINDINGS"] = function()
319 ["PLAYER_LOGIN"] = function()
320 GameTooltip = _G["GameTooltip"];
324 events["LOSS_OF_CONTROL_ADDED"] = events["ACTIONBAR_UPDATE_COOLDOWN"];
325 events["LOSS_OF_CONTROL_UPDATE"] = events["ACTIONBAR_UPDATE_COOLDOWN"]; -- TODO might change once tooltips are in
326 events["SPELL_UPDATE_ICON"] = events["UPDATE_ALL_BUTTONS"];
327 events["PET_STABLE_UPDATE"] = events["UPDATE_ALL_BUTTONS"];
328 events["PET_STABLE_SHOW"] = events["UPDATE_ALL_BUTTONS"];
329 -- TODO overlay glow ? don't exactly know what it does
330 -- autorepeat, tooltips
332 ActionBars:RegisterEvent("PLAYER_LOGIN");
333 ActionBars:RegisterEvent("ACTIONBAR_UPDATE_COOLDOWN");
334 ActionBars:RegisterEvent("SPELL_UPDATE_CHARGES");
335 ActionBars:RegisterEvent("ACTIONBAR_SLOT_CHANGED");
336 ActionBars:RegisterEvent("ACTIONBAR_SHOWGRID");
337 ActionBars:RegisterEvent("ACTIONBAR_HIDEGRID");
338 ActionBars:SetScript("OnEvent", function(self, event, arg1)