Mercurial > wow > reaction
changeset 128:729232aeeb5e
Action Button rewrite. (note: pet actions are probably slightly broken right now, they haven't been updated yet)
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Thu, 05 Mar 2009 01:28:48 +0000 |
parents | 29dacbecdb52 |
children | 28b430de5875 |
files | classes/ActionButton.lua classes/Bar.lua classes/Button.lua classes/GridProxy.lua modules/Action.lua |
diffstat | 5 files changed, 155 insertions(+), 631 deletions(-) [+] |
line wrap: on
line diff
--- a/classes/ActionButton.lua Wed Mar 04 21:19:32 2009 +0000 +++ b/classes/ActionButton.lua Thu Mar 05 01:28:48 2009 +0000 @@ -59,12 +59,19 @@ end self:SetAttribute("action",action) - local hasaction = (action > 120) or self:GetAttribute("hasaction-"..action) - if (self:GetAttribute("showgrid") + self:GetAttribute("showgrid-temp") == 0) and not hasaction then - self:Hide() - else - self:Show() + if not self:GetAttribute("showgrid") then + local hasaction = (action > 120) or self:GetAttribute("hasaction-"..action) + local tempShow = self:GetAttribute("showgrid-temp") + local evtShow = self:GetAttribute("showgrid-event") + if tempShow then tempShow = (tempShow > 0) end + if evtShow then evtShow = (evtShow > 0) end + + if tempShow or evtShow or hasaction then + self:Show() + else + self:Hide() + end end ]] @@ -83,18 +90,20 @@ local _childupdate_showgrid = -- function(self, snippetid, message) [[ - self:SetAttribute("showgrid-temp",message or 0) - local count = (message or 0) + (self:GetAttribute("showgrid") or 0) - if count == 0 then - local action = self:GetAttribute("action") - local hasaction = (action > 120) or self:GetAttribute("hasaction-"..action) - if hasaction then + self:SetAttribute("showgrid-event",message) + if not self:GetAttribute("showgrid") then + local count = message + (self:GetAttribute("showgrid-temp") or 0) + if count <= 0 then + local action = self:GetAttribute("action") + local hasaction = (action > 120) or self:GetAttribute("hasaction-"..action) + if hasaction then + self:Show() + else + self:Hide() + end + else self:Show() - else - self:Hide() end - else - self:Show() end ]] @@ -111,15 +120,11 @@ local _onReceiveDrag = -- function(self, button, kind, value, ...) [[ - if lockButtons and (PlayerInCombat() or not lockButtonsCombat) and not IsModifiedClick("PICKUPACTION") then - return kind, value, ... - else - if kind == "spell" or kind == "item" or kind == "macro" then - -- assume it's a valid action - self:SetAttribute("hasaction-"..self:GetAttribute("action"),true) - end - return "action", self:GetAttribute("action") + if kind == "spell" or kind == "item" or kind == "macro" then + -- assume it's a valid action + self:SetAttribute("hasaction-"..self:GetAttribute("action"),true) end + return "action", self:GetAttribute("action") ]] -- @@ -154,13 +159,14 @@ local Action = setmetatable( { }, { __index = Super } ) ReAction.Button.Action = Action -function Action:New( idx, config, bar, idHint ) +function Action:New( idx, barConfig, bar, idHint ) local name = format("ReAction_%s_Action_%d",bar:GetName(),idx) - self = Super.New(self, name, config, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" ) + self = Super.New(self, name, barConfig, bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" ) local f = self:GetFrame() local barFrame = bar:GetFrame() + local config = self:GetConfig() local frames = { } self.frames = frames @@ -190,9 +196,12 @@ f:SetAttribute("useparent-unit", true) f:SetAttribute("action", config.actionID) f:SetAttribute("default-action", config.actionID) - f:SetAttribute("showgrid",0) + f:SetAttribute("bar-idx",idx) f:SetAttribute("showgrid-temp",0) - f:SetAttribute("bar-idx",idx) + f:SetAttribute("showgrid-event",0) + f:SetAttribute("showgrid",not self:GetBarConfig().hideEmpty) + + self:RefreshHasActionAttributes() -- non secure scripts f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end) @@ -205,7 +214,7 @@ f:SetScript("OnReceiveDrag", function(frame) self:OnReceiveDrag() end) -- secure handlers - f:SetAttribute("_childupate", _childupdate) + f:SetAttribute("_childupdate", _childupdate) f:SetAttribute("_childupdate-showgrid",_childupdate_showgrid) barFrame:WrapScript(f, "OnDragStart", _onDragStart) barFrame:WrapScript(f, "OnReceiveDrag", _onReceiveDrag) @@ -222,13 +231,10 @@ bar:SkinButton(self) -- initial display - self:ShowGrid(not bar:GetConfig().hideEmpty) if ReAction:GetConfigMode() then - self:ShowGrid(true) + self:ShowGridTemp(true) end - f:Show() - self:Refresh() return self @@ -236,37 +242,64 @@ function Action:Destroy() local f = self:GetFrame() + local c = self:GetConfig() f:UnregisterAllEvents() f:SetAttribute("_childupdate-vehicle",nil) - self:ReleaseActionID(config.actionID) - if self.config.pageactions then - for _, id in ipairs(self.config.pageactions) do + self:ReleaseActionID(c.actionID) + if c.pageactions then + for _, id in ipairs(c.pageactions) do self:ReleaseActionID(id) end end - Super:Destroy() + Super.Destroy(self) end function Action:Refresh() self.bar:PlaceButton(self, 36, 36) self:RefreshPages() self:InstallVehicle() + self:ShowGrid(not self:GetBarConfig().hideEmpty) self:UpdateAction() end function Action:InstallVehicle() - if self.idx == 7 and self.bar:GetConfig().vehicle then + if self.idx == 7 and self:GetBarConfig().vehicle then -- install vehicle-exit button on 7th button (only) - f:SetAttribute("_childupdate-vehicle", _childupdate_vehicleExit) - barFrame.ShowVehicleExit = function(bar,show) + self:GetFrame():SetAttribute("_childupdate-vehicle", _childupdate_vehicleExit) + self:GetBar():GetFrame().ShowVehicleExit = function(bar,show) self:ShowVehicleExit(show) end else - f:SetAttribute("_childupdate-vehicle",nil) + self:GetFrame():SetAttribute("_childupdate-vehicle",nil) + end +end + +function Action:ShowGrid( show ) + if not InCombatLockdown() then + self.frame:SetAttribute("showgrid", show) + self:UpdateShowGrid() + end +end + +function Action:ShowGridTemp( show ) + -- This function only modifies the show-grid when out + -- of combat, and is ignored by the secure handler. Use + -- it for configuration modes. + if not InCombatLockdown() then + local count = self.showGridTempCount or 0 + if show then + count = count + 1 + else + count = count - 1 + end + if count < 0 then count = 0 end + self.showGridTempCount = count + self:GetFrame():SetAttribute("showgrid-temp",count) + self:UpdateShowGrid() end end @@ -293,28 +326,48 @@ end end +function Action:RefreshHasActionAttributes() + -- check if each action has an action or not, and flag an attribute + -- so that the showgrid secure handler can make decisions accordingly + local f = self:GetFrame() + local attr = "hasaction-"..self.config.actionID + local hasAction = HasAction(self.config.actionID) + if f:GetAttribute(attr) ~= hasAction then + f:SetAttribute(attr,hasAction) -- avoid setting attribute and triggering script handler unnecessarily + end + if self.config.pageactions then + for i = 1, self.nPages do + attr = "hasaction-"..self.config.pageactions[i] + hasAction = HasAction(self.config.pageactions[i]) + if f:GetAttribute(attr) ~= hasAction then + f:SetAttribute(attr,hasAction) + end + end + end +end + function Action:UpdateShowGrid() -- this is a little bit complicated because there's no - -- secure driver to handle show/hide grid events. + -- secure access to HasAction. if InCombatLockdown() then self.showgridPending = true -- handle after combat else self.showgridPending = false - -- check if each action has an action or not, and flag an attribute - -- so that the showgrid secure handler can make decisions accordingly - local f = self:GetFrame() - f:SetAttribute("hasaction-"..self.config.actionID, HasAction(self.config.actionID)) - if self.config.pageactions then - for i = 1, self.nPages do - f:SetAttribute("hasaction-"..self.config.pageactions[i], HasAction(self.config.pageactions[i])) - end - end + self:RefreshHasActionAttributes() + -- the following is an out-of-combat show/hide to supplement the secure -- handling and clean up after it when it guesses - if HasAction(self.actionID) then + local f = self:GetFrame() + local count = (f:GetAttribute("showgrid-event") or 0) + + (self.showGridTempCount or 0) + + (f:GetAttribute("showgrid") and 1 or 0) + + if count <= 0 and not HasAction(self.actionID) then + if f:IsShown() then + f:Hide() + end + elseif not f:IsShown() then f:Show() - else - f:Hide() end end end @@ -507,7 +560,7 @@ end function Action:RefreshPages( force ) - local nPages = self.bar:GetConfig().nPages + local nPages = self:GetBarConfig().nPages if nPages and (nPages ~= self.nPages or force) then local f = self:GetFrame() local c = self.config.pageactions @@ -532,11 +585,10 @@ end end -function Action.SetupBarHeader( bar ) -- call this as a static method +function Action.SetupBarHeader( bar, config ) -- call this as a static method local f = bar:GetFrame() - local c = bar:GetConfig() - f:SetAttribute("mindcontrol",c.mindcontrol) - f:SetAttribute("vehicle",c.vehicle) + f:SetAttribute("mindcontrol",config.mindcontrol) + f:SetAttribute("vehicle",config.vehicle) f:Execute( [[ doMindControl = self:GetAttribute("mindcontrol") @@ -547,8 +599,8 @@ f:SetAttribute("_onstate-mc", _onstate_mc) RegisterStateDriver(f, "mc", "[target=vehicle,exists] vehicle; [bonusbar:5] mc; none") - f:SetAttribute("lockbuttons",c.lockButtons) - f:SetAttribute("lockbuttonscombat",c.lockButtonsCombat) + f:SetAttribute("lockbuttons",config.lockButtons) + f:SetAttribute("lockbuttonscombat",config.lockButtonsCombat) f:Execute( [[ lockButtons = self:GetAttribute("lockbuttons") @@ -572,7 +624,7 @@ function Action:ShowVehicleExit(show) local f = self:GetFrame() local tx = f.vehicleExitTexture - if show and self.bar:GetConfig().vehicle then + if show and self:GetBarConfig().vehicle then if not tx then tx = f:CreateTexture(nil,"ARTWORK") tx:SetAllPoints() @@ -629,7 +681,7 @@ function Action:ACTIONBAR_SLOT_CHANGED(event, action) if action == 0 or action == self.actionID then - self:UpdateAction() + self:UpdateAll() end end
--- a/classes/Bar.lua Wed Mar 04 21:19:32 2009 +0000 +++ b/classes/Bar.lua Thu Mar 05 01:28:48 2009 +0000 @@ -84,6 +84,9 @@ function Bar:OnConfigModeChanged(event, mode) self:ShowControls(mode) -- Bar:ShowControls() defined in Overlay.lua + for b in pairs(self.buttons) do + b:ShowGridTemp(mode) + end end function Bar:ApplyAnchor()
--- a/classes/Button.lua Wed Mar 04 21:19:32 2009 +0000 +++ b/classes/Button.lua Thu Mar 05 01:28:48 2009 +0000 @@ -30,7 +30,7 @@ ReAction.Button = Button -- export to ReAction -function Button:New( name, config, bar, idx, inherits, buttonType ) +function Button:New( name, barConfig, bar, idx, inherits, buttonType ) buttonType = buttonType or "CheckButton" -- create new self @@ -38,7 +38,8 @@ { bar = bar, idx = idx, - config = config, + barConfig = barConfig, + config = barConfig.buttons[idx], name = name, }, { __index = self } ) @@ -84,6 +85,10 @@ end end +function Button:GetBar() + return self.bar +end + function Button:GetFrame() return self.frame end @@ -96,6 +101,12 @@ return self.config end +function Button:GetBarConfig() + -- this is the per-bar Button config structure, + -- not the config structure of the bar itself + return self.barConfig +end + function Button:GetActionID() -- derived classes should override this return nil @@ -180,6 +191,7 @@ f:SetScript("OnEnter", self.oldOnEnter) self.oldOnEnter = nil end + self:ShowGridTemp(mode) self:UpdateKeybindModeDisplay( mode ) end @@ -256,23 +268,14 @@ end end -function Button:ShowGrid( show ) - if not InCombatLockdown() then - local f = self.frame - local count = f:GetAttribute("showgrid") - if show then - count = count + 1 - else - count = count - 1 - end - if count < 0 then - count = 0 - end - f:SetAttribute("showgrid",count) - self:UpdateShowGrid() - end -end - function Button:UpdateShowGrid() -- does nothing by default end + +function Button:ShowGridTemp(show) + -- does nothing by default +end + +function Button:ShowGrid(show) + -- does nothing by default +end
--- a/classes/GridProxy.lua Wed Mar 04 21:19:32 2009 +0000 +++ b/classes/GridProxy.lua Thu Mar 05 01:28:48 2009 +0000 @@ -4,7 +4,7 @@ local gridProxy = { } ReAction.gridProxy = gridProxy -local f = CreateFrame("CheckButton",nil,UIParent,"ActionBarButtonTemplate, SecureHandlerAttributeTemplate") +local f = CreateFrame("CheckButton","ReActionShowGridProxy",UIParent,"ActionBarButtonTemplate, SecureHandlerAttributeTemplate") -- SecureHandlerAttributeTemplate overwrites the onAttributeChanged handler, as it's last in the list f:UnregisterAllEvents() f:SetScript("OnEnter",nil) @@ -13,6 +13,9 @@ f:SetScript("OnDragStart",nil) f:SetScript("OnReceiveDrag",nil) f:SetScript("OnUpdate",nil) +f:SetAttribute("showgrid",0) +f:SetAttribute("action",0) +f.action = 0 f:EnableMouse(false) for _, child in ipairs({f:GetChildren()}) do child:Hide()
--- a/modules/Action.lua Wed Mar 04 21:19:32 2009 +0000 +++ b/modules/Action.lua Thu Mar 05 01:28:48 2009 +0000 @@ -1,14 +1,3 @@ ---[[ - ReAction Action button module. - - The button module implements standard action button functionality by wrapping Blizzard's - ActionBarButtonTemplate frame and associated functions. - - It also provides action remapping support for multiple pages and possessed targets - (Mind Control, Eyes of the Beast, Karazhan Chess event, various quests, etc). ---]] - --- local imports local ReAction = ReAction local L = ReAction.L local _G = _G @@ -22,14 +11,13 @@ -- libraries local KB = LibStub("LibKeyBound-1.0") -local LBF -- initialized later -- module declaration local moduleID = "Action" local module = ReAction:NewModule( moduleID ) -- Class declarations -local Button = { } +local Button = ReAction.Button.Action -- see /classes/ActionButton.lua local Handle = { } local PropHandler = { } @@ -53,8 +41,6 @@ ReAction.RegisterCallback(self, "OnRenameBar") ReAction.RegisterCallback(self, "OnConfigModeChanged") - LBF = LibStub("LibButtonFacade",true) - KB.RegisterCallback(self, "LIBKEYBOUND_ENABLED") KB.RegisterCallback(self, "LIBKEYBOUND_DISABLED") KB.RegisterCallback(self, "LIBKEYBOUND_MODE_COLOR_CHANGED","LIBKEYBOUND_ENABLED") @@ -121,14 +107,12 @@ function module:LIBKEYBOUND_ENABLED(evt) for _, h in pairs(self.handles) do - h:ShowGrid(true) h:SetKeybindMode(true) end end function module:LIBKEYBOUND_DISABLED(evt) for _, h in pairs(self.handles) do - h:ShowGrid(false) h:SetKeybindMode(false) end end @@ -160,7 +144,6 @@ desc = L["Prevents picking up/dragging actions.|nNOTE: This setting is overridden by the global setting in Blizzard's Action Buttons tab"], order = 2, type = "toggle", - disabled = "LockButtonsDisabled", get = "GetLockButtons", set = "SetLockButtons", }, @@ -307,7 +290,9 @@ btnCfg[i] = {} end if self.btns[i] == nil then - local b = Button:New(self, i, btnCfg[i], self.config) + local lastButton = self:GetLastButton() + local hint = lastButton and lastButton.config.actionID + local b = Button:New(i, self.config, self.bar, hint) self.btns[i] = b self.bar:AddButton(i,b) end @@ -321,31 +306,10 @@ end end end - local f = self.bar:GetFrame() for _, b in ipairs(self.btns) do b:Refresh() end - f:SetAttribute("mindcontrol",self.config.mindcontrol) - f:SetAttribute("vehicle",self.config.vehicle) - f:Execute( - [[ - doMindControl = self:GetAttribute("mindcontrol") - doVehicle = self:GetAttribute("vehicle") - control:ChildUpdate() - ]]) - - f:SetAttribute("_onstate-mc", - -- function _onstate-mc(self, stateid, newstate) - [[ - local oldMcVehicleState = mcVehicleState - mcVehicleState = newstate - control:ChildUpdate() - if oldMcVehicleState == "vehicle" or mcVehicleState == "vehicle" then - control:ChildUpdate("vehicle") - end - ]]) - RegisterStateDriver(f, "mc", "[target=vehicle,exists] vehicle; [bonusbar:5] mc; none") - + Button.SetupBarHeader(self.bar,self.config) self:UpdateButtonLock() end @@ -359,26 +323,12 @@ function Handle:SetConfigMode(mode) for _, b in pairs(self.btns) do - b:ShowGrid(mode) - b:ShowActionIDLabel(mode) - end - end - - function Handle:ShowGrid(show) - for _, b in pairs(self.btns) do - b:ShowGrid(show) + b:UpdateActionIDLabel(mode) end end function Handle:UpdateButtonLock() - local f = self.bar:GetFrame() - f:SetAttribute("lockbuttons",self.config.lockButtons) - f:SetAttribute("lockbuttonscombat",self.config.lockButtonsCombat) - f:Execute( - [[ - lockButtons = self:GetAttribute("lockbuttons") - lockButtonsCombat = self:GetAttribute("lockbuttonscombat") - ]]) + Button.SetButtonLock(self.bar, self.config.lockButtons, self.config.lockButtonsCombat) end function Handle:SetKeybindMode(mode) @@ -404,7 +354,9 @@ function Handle:SetHideEmpty(info, value) if value ~= self.config.hideEmpty then self.config.hideEmpty = value - self:ShowGrid(not value) + for _, b in pairs(self.btns) do + b:ShowGrid(not value) + end end end @@ -413,7 +365,7 @@ end function Handle:GetLockButtons() - return LOCK_ACTIONBAR == "1" or self.config.lockButtons + return self.config.lockButtons end function Handle:SetLockButtons(info, value) @@ -421,10 +373,6 @@ self:UpdateButtonLock() end - function Handle:LockButtonsDisabled() - return LOCK_ACTIONBAR == "1" - end - function Handle:GetLockButtonsCombat() return self.config.lockButtonsCombat end @@ -435,7 +383,7 @@ end function Handle:LockButtonsCombatDisabled() - return LOCK_ACTIONBAR == "1" or not self.config.lockButtons + return not self.config.lockButtons end function Handle:GetNumPages() @@ -705,495 +653,3 @@ end ------- ActionID allocation ------ --- this needs to be high performance when requesting new IDs, --- or certain controls will become sluggish. However, the new-request --- infrastructure can be built lazily the first time that a new request --- comes in (which will only happen at user config time: at static startup --- config time all actionIDs should already have been assigned and stored --- in the config file) - -local IDAlloc -do - local n = 120 - - IDAlloc = setmetatable({ wrap = 1, freecount = n }, {__index = function() return 0 end}) - - function IDAlloc:Acquire(id, hint) - id = tonumber(id) - hint = tonumber(hint) - if id and (id < 1 or id > n) then - id = nil - end - if hint and (hint < 1 or hint > n) then - hint = nil - end - if id == nil then - -- get a free ID - if hint and self[hint] == 0 then - -- use the hint if it's free - id = hint - elseif self.freecount > 0 then - -- if neither the id nor the hint are defined or free, but - -- the list is known to have free IDs, then start searching - -- at the hint for a free one - for i = hint or 1, n do - if self[i] == 0 then - id = i - break - end - end - -- self.wrap the search - if id == nil and hint and hint > 1 then - for i = 1, hint - 1 do - if self[i] == 0 then - id = i - break - end - end - end - end - if id == nil then - -- if there are no free IDs, start wrapping at 1 - id = self.wrap - self.wrap = id + 1 - if self.wrap > n then - self.wrap = 1 - end - end - end - if self[id] == 0 then - self.freecount = self.freecount - 1 - end - self[id] = self[id] + 1 - return id - end - - function IDAlloc:Release(id) - id = tonumber(id) - if id and (id >= 1 or id <= n) then - self[id] = self[id] - 1 - if self[id] == 0 then - self.freecount = self.freecount + 1 - self.wrap = 1 - end - end - end -end - ------- Button class ------ -local frameRecycler = { } -local trash = CreateFrame("Frame") -local OnUpdate, GetActionName, GetHotkey -do - local ATTACK_BUTTON_FLASH_TIME = ATTACK_BUTTON_FLASH_TIME - local IsActionInRange = IsActionInRange - - function OnUpdate(frame, elapsed) - -- note: This function taints frame.flashtime and frame.rangeTimer. Both of these - -- are only read by ActionButton_OnUpdate (which this function replaces). In - -- all other places they're just written, so it doesn't taint any secure code. - if frame.flashing == 1 then - frame.flashtime = frame.flashtime - elapsed - if frame.flashtime <= 0 then - local overtime = -frame.flashtime - if overtime >= ATTACK_BUTTON_FLASH_TIME then - overtime = 0 - end - frame.flashtime = ATTACK_BUTTON_FLASH_TIME - overtime - - local flashTexture = frame.flash - if flashTexture:IsShown() then - flashTexture:Hide() - else - flashTexture:Show() - end - end - end - - if frame.rangeTimer then - frame.rangeTimer = frame.rangeTimer - elapsed; - - if frame.rangeTimer <= 0 then - if IsActionInRange(frame.action) == 0 then - frame.icon:SetVertexColor(1.0,0.1,0.1) - else - ActionButton_UpdateUsable(frame) - end - frame.rangeTimer = 0.1 - end - end - end - - function GetActionName(f) - local b = f and f._reactionButton - if b then - return format("%s:%s", b.bar:GetName(), b.idx) - end - end - - function GetHotkey(f) - return KB:ToShortKey(GetBindingKey(format("CLICK %s:LeftButton",f:GetName()))) - end - - -- This is a bit hokey : install a bare hook on ActionButton_UpdateHotkey because - -- even though it's secure it's never called in a way that can cause taint. This is - -- for performance reasons to avoid having to hook frame:OnEvent securely. - local UpdateHotkey_old = ActionButton_UpdateHotkeys - ActionButton_UpdateHotkeys = function( frame, ... ) - local b = frame._reactionButton - if b then - b.hotkey:SetText( GetHotkey(frame) ) - else - return UpdateHotkey_old(frame, ...) - end - end -end - -local meta = {__index = Button} - -function Button:New( handle, idx, config, barConfig ) - local bar = handle.bar - - -- create new self - self = setmetatable( - { - bar = bar, - idx = idx, - config = config, - barConfig = barConfig, - }, meta ) - - local name = config.name or ("ReAction_%s_%s_%d"):format(bar:GetName(),moduleID,idx) - self.name = name - config.name = name - local lastButton = handle:GetLastButton() - config.actionID = IDAlloc:Acquire(config.actionID, lastButton and lastButton.config.actionID) -- gets a free one if none configured - self.nPages = 1 - - -- have to recycle frames with the same name: CreateFrame() doesn't overwrite - -- existing globals. Can't set to nil in the global because it's then tainted. - local parent = bar:GetFrame() - local f = frameRecycler[name] - if f then - f:SetParent(parent) - else - f = CreateFrame("CheckButton", name, parent, "ActionBarButtonTemplate") - -- ditch the old hotkey text because it's tied in ActionButton_Update() to the - -- standard binding. - local hotkey = _G[name.."HotKey"] - hotkey:SetParent(trash) - hotkey = f:CreateFontString(nil, "ARTWORK", "NumberFontNormalSmallGray") - hotkey:SetWidth(36) - hotkey:SetHeight(18) - hotkey:SetJustifyH("RIGHT") - hotkey:SetJustifyV("TOP") - hotkey:SetPoint("TOPLEFT",f,"TOPLEFT",-2,-2) - f.hotkey = hotkey - f.icon = _G[name.."Icon"] - f.flash = _G[name.."Flash"] - f:SetScript("OnUpdate",OnUpdate) - end - - f._reactionButton = self - - self.hotkey = f.hotkey - self.border = _G[name.."Border"] - - f:SetAttribute("action", config.actionID) - f:SetAttribute("default-action", config.actionID) - -- install mind control actions for all buttons just for simplicity - if self.idx <= 12 then - f:SetAttribute("mc-action", 120 + self.idx) - end - - -- set a tooltip onEnter - f:SetScript("OnEnter", - function(frame) - if ReAction:GetKeybindMode() then - KB:Set(frame) - elseif frame.vehicleExitMode then - GameTooltip_AddNewbieTip(frame, LEAVE_VEHICLE, 1.0, 1.0, 1.0, nil); - else - ActionButton_SetTooltip(frame) - end - end) - - -- set a _childupdate handler, called within the header's context - f:SetAttribute("_childupdate", - -- function _childupdate(self, snippetid, message) - [[ - local action = "default-action" - if (doVehicle and mcVehicleState == "vehicle") or - (doMindControl and mcVehicleState == "mc") then - action = "mc-action" - elseif page and state and page[state] then - action = "action-"..page[state] - end - - local value = self:GetAttribute(action) - if value then - self:SetAttribute("action",value) - end - ]]) - - -- Install a handler for the 7th button (only) to show/hide a - -- vehicle exit button. This is more than a little bit hack-ish and - -- will be replaced in the next iteration with the reimplementation - -- of action button functionality. - if idx == 7 then - local barFrame = bar:GetFrame() - function barFrame:ShowVehicleExit(show) - local tx = f.vehicleExitTexture - if show then - if not tx then - tx = f:CreateTexture(nil,"ARTWORK") - tx:SetAllPoints() - -- copied from Blizzard/VehicleMenuBar.lua SkinsData - tx:SetTexture("Interface\\Vehicles\\UI-Vehicles-Button-Exit-Up") - tx:SetTexCoord(0.140625, 0.859375, 0.140625, 0.859375) - f.vehicleExitTexture = tx - end - tx:Show() - f.vehicleExitMode = true - elseif tx then - tx:SetTexCoord(0,1,0,1) - tx:Hide() - f.vehicleExitMode = false - end - end - - f:SetAttribute("macrotext","/run VehicleExit()") - f:SetAttribute("_childupdate-vehicle", - -- function _childupdate-vehicle(self, snippetid, message) - [[ - local show = (mcVehicleState == "vehicle") - if show then - self:SetAttribute("type","macro") - self:SetAttribute("showgrid",self:GetAttribute("showgrid")+1) - self:Show() - else - self:SetAttribute("type","action") - local showgrid = self:GetAttribute("showgrid") - showgrid = showgrid - 1 - if showgrid < 0 then showgrid = 0 end - self:SetAttribute("showgrid",self:GetAttribute("showgrid")-1) - if showgrid <= 0 then - self:Hide() - end - end - control:CallMethod("ShowVehicleExit",show) - ]]) - end - - -- install drag wrappers to lock buttons - bar:GetFrame():WrapScript(f, "OnDragStart", - -- OnDragStart(self, button, kind, value, ...) - [[ - if lockButtons and (PlayerInCombat() or not lockButtonsCombat) and not IsModifiedClick("PICKUPACTION") then - return "clear" - end - ]]) - - self.frame = f - - -- initialize the hide state - f:SetAttribute("showgrid",0) - self:ShowGrid(not barConfig.hideEmpty) - if ReAction:GetConfigMode() then - self:ShowGrid(true) - end - - -- set the hotkey text - self.hotkey:SetText( GetHotkey(self.frame) ) - - -- show the ID label if applicable - self:ShowActionIDLabel(ReAction:GetConfigMode()) - - -- attach to skinner - bar:SkinButton(self, - { - HotKey = self.hotkey, - } - ) - - self:Refresh() - return self -end - -function Button:Destroy() - local f = self.frame - f:UnregisterAllEvents() - f:Hide() - f:SetParent(UIParent) - f:ClearAllPoints() - f:SetAttribute("_childupdate",nil) - f:SetAttribute("_childupdate-vehicle",nil) - if self.name then - frameRecycler[self.name] = f - end - if self.config.actionID then - IDAlloc:Release(self.config.actionID) - end - if self.config.pageactions then - for _, id in ipairs(self.config.pageactions) do - IDAlloc:Release(id) - end - end - f._reactionButton = nil - self.frame = nil - self.config = nil - self.bar = nil -end - -function Button:Refresh() - local f = self.frame - self.bar:PlaceButton(self, 36, 36) - self:RefreshPages() -end - -function Button:GetFrame() - return self.frame -end - -function Button:GetName() - return self.name -end - -function Button:GetConfig() - return self.config -end - -function Button:GetActionID(page) - if page == nil then - -- get the effective ID - return self.frame.action -- kept up-to-date by Blizzard's ActionButton_CalculateAction() - else - if page == 1 then - return self.config.actionID - else - return self.config.pageactions and self.config.pageactions[page] or self.config.actionID - end - end -end - -function Button:SetActionID( id, page ) - id = tonumber(id) - page = tonumber(page) - if id == nil or id < 1 or id > 120 then - error("Button:SetActionID - invalid action ID") - end - if page and page ~= 1 then - if not self.config.pageactions then - self.config.pageactions = { } - end - if self.config.pageactions[page] then - IDAlloc:Release(self.config.pageactions[page]) - end - self.config.pageactions[page] = id - IDAlloc:Acquire(self.config.pageactions[page]) - self.frame:SetAttribute(("action-page%d"):format(page),id) - else - IDAlloc:Release(self.config.actionID) - self.config.actionID = id - IDAlloc:Acquire(self.config.actionID) - self.frame:SetAttribute("action",id) - if self.config.pageactions then - self.config.pageactions[1] = id - self.frame:SetAttribute("action-page1",id) - end - end -end - -function Button:RefreshPages( force ) - local nPages = self.barConfig.nPages - if nPages and (nPages ~= self.nPages or force) then - local f = self:GetFrame() - local c = self.config.pageactions - if nPages > 1 and not c then - c = { } - self.config.pageactions = c - end - for i = 1, nPages do - if i > 1 then - c[i] = IDAlloc:Acquire(c[i], self.config.actionID + (i-1)*self.bar:GetNumButtons()) - else - c[i] = self.config.actionID -- page 1 is the same as the base actionID - end - f:SetAttribute(("action-page%d"):format(i),c[i]) - end - for i = nPages+1, #c do - IDAlloc:Release(c[i]) - c[i] = nil - f:SetAttribute(("action-page%d"):format(i),nil) - end - self.nPages = nPages - end -end - -function Button:ShowGrid( show ) - if not InCombatLockdown() then - local f = self.frame - local count = f:GetAttribute("showgrid") - if show then - count = count + 1 - else - count = count - 1 - end - if count < 0 then - count = 0 - end - f:SetAttribute("showgrid",count) - - if count >= 1 and not f:GetAttribute("statehidden") then - if LBF then - LBF:SetNormalVertexColor(self.frame, 1.0, 1.0, 1.0, 0.5) - else - self.frame:GetNormalTexture():SetVertexColor(1.0, 1.0, 1.0, 0.5); - end - f:Show() - elseif count < 1 and not HasAction(self:GetActionID()) then - f:Hide() - end - end -end - -function Button:ShowActionIDLabel( show ) - local f = self:GetFrame() - if show then - local id = self:GetActionID() - if not f.actionIDLabel then - local label = f:CreateFontString(nil,"OVERLAY","GameFontNormalLarge") - label:SetAllPoints() - label:SetJustifyH("CENTER") - label:SetShadowColor(0,0,0,1) - label:SetShadowOffset(2,-2) - f.actionIDLabel = label -- store the label with the frame for recycling - - f:HookScript("OnAttributeChanged", - function(frame, attr, value) - if label:IsVisible() and attr:match("action") then - label:SetText(tostring(frame.action)) - end - end) - end - f.actionIDLabel:SetText(tostring(id)) - f.actionIDLabel:Show() - elseif f.actionIDLabel then - f.actionIDLabel:Hide() - end -end - -function Button:SetKeybindMode( mode ) - if mode then - self.frame.GetActionName = GetActionName - self.frame.GetHotkey = GetHotkey - -- set the border for all buttons to the keybind-enable color - self.border:SetVertexColor(KB:GetColorKeyBoundMode()) - self.border:Show() - elseif IsEquippedAction(self:GetActionID()) then - self.border:SetVertexColor(0, 1.0, 0, 0.35) -- from ActionButton.lua - else - self.border:Hide() - end -end \ No newline at end of file