Mercurial > wow > reaction
view classes/ActionButton.lua @ 151:57568d3ff3e6
fixed bags not showing when initially placed
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Fri, 08 May 2009 00:35:14 +0000 |
parents | 42cade25d40d |
children | 806a61b331a0 |
line wrap: on
line source
local ReAction = ReAction local L = ReAction.L local _G = _G local CreateFrame = CreateFrame local format = string.format local IsUsableAction = IsUsableAction local IsEquippedAction = IsEquippedAction local IsConsumableAction = IsConsumableAction local IsStackableAction = IsStackableAction local GetActionText = GetActionText local GetCVar = GetCVar local GameTooltip_SetDefaultAnchor = GameTooltip_SetDefaultAnchor local IsCurrentAction = IsCurrentAction local IsAutoRepeatAction = IsAutoRepeatAction local IsUsableAction = IsUsableAction local IsAttackAction = IsAttackAction local CooldownFrame_SetTimer = CooldownFrame_SetTimer local GetActionCooldown = GetActionCooldown local GetActionTexture = GetActionTexture local ATTACK_BUTTON_FLASH_TIME = ATTACK_BUTTON_FLASH_TIME local TOOLTIP_UPDATE_TIME = TOOLTIP_UPDATE_TIME local IsActionInRange = IsActionInRange local InCombatLockdown = InCombatLockdown local HasAction = HasAction ReAction:UpdateRevision("$Revision: 154 $") -- -- Secure snippets -- These are run within the context of the bar's sandbox, as the -- buttons themselves do not have their own sandbox. -- local _onstate_mc = -- function(self, stateid, newstate) [[ local oldMcVehicleState = mcVehicleState mcVehicleState = newstate control:ChildUpdate() if oldMcVehicleState == "vehicle" or mcVehicleState == "vehicle" then control:ChildUpdate("vehicle") end ]] local _childupdate = -- function(self, snippetid, message) [[ local action = nil if (doVehicle and mcVehicleState == "vehicle") or (doMindControl and mcVehicleState == "mc") then local idx = self:GetAttribute("bar-idx") local maxN = (doVehicle and mcVehicleState == "vehicle") and 7 or 12 if idx and idx <= maxN then action = 120 + idx else action = 0 end elseif page and state and page[state] then action = self:GetAttribute("action-"..page[state]) end if action == nil then action = self:GetAttribute("default-action") end self:SetAttribute("action",action) 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 ]] local _childupdate_vehicleExit = -- function(self, snippetid, message) [[ local show = (mcVehicleState == "vehicle") if show and doVehicle then self:SetAttribute("type","macro") self:Show() else self:SetAttribute("type","action") end control:CallMethod("ShowVehicleExit",show) ]] local _childupdate_showgrid = -- function(self, snippetid, message) [[ 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() end end ]] local _onDragStart = -- function(self, button, kind, value, ...) [[ if lockButtons and (PlayerInCombat() or not lockButtonsCombat) and not IsModifiedClick("PICKUPACTION") then return kind, value, ... else -- don't make any assumptions about hiding on grid show here, as we don't know if the -- drag gets cancelled later. return "action", self:GetAttribute("action") end ]] local _onReceiveDrag = -- function(self, button, kind, value, ...) [[ if kind ~= "spell" and kind ~= "item" and kind ~= "macro" then return kind, value, ... end self:SetAttribute("hasaction-"..self:GetAttribute("action"),true) return "action", self:GetAttribute("action") ]] -- -- private -- local eventList = { "PLAYER_REGEN_ENABLED", "PLAYER_ENTERING_WORLD", "ACTIONBAR_PAGE_CHANGED", "ACTIONBAR_SLOT_CHANGED", "UPDATE_BINDINGS", "ACTIONBAR_UPDATE_STATE", "ACTIONBAR_UPDATE_USABLE", "ACTIONBAR_UPDATE_COOLDOWN", "UPDATE_INVENTORY_ALERTS", "PLAYER_TARGET_CHANGED", "TRADE_SKILL_SHOW", "TRADE_SKILL_CLOSE", "PLAYER_ENTER_COMBAT", "PLAYER_LEAVE_COMBAT", "START_AUTOREPEAT_SPELL", "STOP_AUTOREPEAT_SPELL", "UNIT_ENTERED_VEHICLE", "UNIT_EXITED_VEHICLE", "COMPANION_UPDATE", } -- -- Action Button class -- local Super = ReAction.Button local Action = setmetatable( { }, { __index = Super } ) ReAction.Button.Action = Action function Action:New( idx, barConfig, bar, idHint ) local name = format("ReAction_%s_Action_%d",bar:GetName(),idx) self = Super.New(self, name, barConfig.buttons[idx], bar, idx, "SecureActionButtonTemplate, ActionButtonTemplate" ) self.barConfig = barConfig local f = self:GetFrame() local barFrame = bar:GetFrame() local config = self:GetConfig() self.rangeTimer = TOOLTIP_UPDATE_TIME -- set up the base action ID self:SetActionIDPool("action",120) config.actionID = self:AcquireActionID(config.actionID, idHint) self.nPages = 1 -- attribute setup f:SetAttribute("type","action") f:SetAttribute("checkselfcast", true) f:SetAttribute("checkfocuscast", true) f:SetAttribute("action", config.actionID) f:SetAttribute("default-action", config.actionID) f:SetAttribute("bar-idx",idx) f:SetAttribute("showgrid-temp",0) f:SetAttribute("showgrid-event",0) f:SetAttribute("showgrid",not self:GetBarConfig().hideEmpty) -- non secure scripts f:SetScript("OnEvent", function(frame, ...) self:OnEvent(...) end) f:SetScript("OnEnter", function(frame) self:OnEnter() end) f:SetScript("OnLeave", function(frame) self:OnLeave() end) f:SetScript("OnAttributeChanged", function(frame, attr, value) self:OnAttributeChanged(attr, value) end) f:SetScript("PostClick", function(frame, ...) self:PostClick(...) end) f:SetScript("OnUpdate", function(frame, elapsed) self:OnUpdate(elapsed) end) f:SetScript("OnDragStart", function(frame) self:OnDragStart() end) f:SetScript("OnReceiveDrag", function(frame) self:OnReceiveDrag() end) -- event registration f:EnableMouse(true) f:RegisterForDrag("LeftButton", "RightButton") f:RegisterForClicks("AnyUp") for _, evt in pairs(eventList) do f:RegisterEvent(evt) end -- secure handlers f:SetAttribute("_childupdate", _childupdate) f:SetAttribute("_childupdate-showgrid",_childupdate_showgrid) barFrame:WrapScript(f, "OnDragStart", _onDragStart) barFrame:WrapScript(f, "OnReceiveDrag", _onReceiveDrag) -- attach to skinner bar:SkinButton(self) -- initial display if ReAction:GetConfigMode() then self:ShowGridTemp(true) end self:Refresh() return self end function Action:Destroy() local f = self:GetFrame() local c = self:GetConfig() f:SetAttribute("_childupdate-vehicle",nil) f:SetAttribute("action",c.actionID) -- so that Super.Destroy releases the right one if c.pageactions and #c.pageactions > 1 then for i = 2, #c.pageactions do self:ReleaseActionID(c.pageactions[i]) self:ReleaseActionID(id) end end Super.Destroy(self) end function Action:GetBarConfig() -- this is the per-bar Action module config structure, -- not the config structure of the bar itself return self.barConfig end function Action:Refresh() Super.Refresh(self) self:RefreshHasActionAttributes() self:RefreshPages() self:InstallVehicle() self:ShowGrid(not self:GetBarConfig().hideEmpty) self:UpdateAction() end function Action:InstallVehicle() local f = self:GetFrame() if self.idx == 7 and self:GetBarConfig().vehicle then -- install vehicle-exit button on 7th button (only) f:SetAttribute("_childupdate-vehicle", _childupdate_vehicleExit) f:SetAttribute("macrotext","/run VehicleExit()") self:GetBar():GetFrame().ShowVehicleExit = function(bar,show) self:ShowVehicleExit(show) end else f:SetAttribute("_childupdate-vehicle",nil) f:SetAttribute("macrotext",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 function Action:UpdateAll() self:UpdateActionIDLabel(ReAction:GetConfigMode()) self:UpdateHotkey() self:UpdateShowGrid() self:UpdateIcon() self:UpdateBorder() self:UpdateMacroText() self:UpdateCount() self:UpdateTooltip() self:UpdateCheckedState() self:UpdateUsable() self:UpdateCooldown() self:UpdateFlash() end function Action:UpdateAction() local action = self:GetActionID() if action ~= self.actionID then self.actionID = action self:UpdateAll() 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 access to HasAction. if InCombatLockdown() then self.showgridPending = true -- handle after combat else self.showgridPending = false self:RefreshHasActionAttributes() -- the following is an out-of-combat show/hide to supplement the secure -- handling and clean up after it when it guesses 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() end end end function Action:UpdateIcon() local action = self.actionID local texture = GetActionTexture(action) local icon = self.frames.icon local hotkey = self.frames.hotkey local f = self:GetFrame() if self.vehicleExitMode then texture = "Interface\\Vehicles\\UI-Vehicles-Button-Exit-Up" icon:SetTexCoord(0.140625, 0.859375, 0.140625, 0.859375) icon:SetVertexColor(1,0,0) else icon:SetTexCoord(0,1,0,1) end if texture then icon:SetTexture(texture) icon:Show() self.rangeTimer = -1 f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2") else icon:Hide() self.frames.cooldown:Hide() self.rangeTimer = nil if self.vehicleExitMode then f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot2") else f:SetNormalTexture("Interface\\Buttons\\UI-Quickslot") end end end function Action:UpdateBorder() local action = self.actionID if ReAction:GetKeybindMode() then self:UpdateKeybindModeDisplay(true) elseif IsEquippedAction(action) then self.frames.border:SetVertexColor(0, 1.0, 0, 0.35) self.frames.border:Show() else self.frames.border:Hide() end end function Action:UpdateMacroText() local action = self.actionID if not IsConsumableAction(action) and not IsStackableAction(action) then self.frames.name:SetText(GetActionText(action)) else self.frames.name:SetText("") end end function Action:UpdateCount() local action = self.actionID if IsConsumableAction(action) or IsStackableAction(action) then self.frames.count:SetText(GetActionCount(action)) else self.frames.count:SetText("") end end function Action:UpdateTooltip() local f = self:GetFrame() if GameTooltip:GetOwner() == f then self:SetTooltip() end end function Action:SetTooltip() local f = self:GetFrame() if GetCVar("UberTooltips") == "1" then GameTooltip_SetDefaultAnchor(GameTooltip, f) else GameTooltip:SetOwner(f) end GameTooltip:SetAction(self.actionID) end function Action:UpdateCheckedState() local action = self.actionID if IsCurrentAction(action) or IsAutoRepeatAction(action) then self:GetFrame():SetChecked(1) else self:GetFrame():SetChecked(0) end end function Action:UpdateUsable() local isUsable, notEnoughMana = IsUsableAction(self.actionID) if isUsable or self.vehicleExitMode then self.frames.icon:SetVertexColor(1.0, 1.0, 1.0) self.frames.normalTexture:SetVertexColor(1.0, 1.0, 1.0) elseif notEnoughMana then self.frames.icon:SetVertexColor(0.5, 0.5, 1.0) self.frames.normalTexture:SetVertexColor(0.5, 0.5, 1.0) else self.frames.icon:SetVertexColor(0.4, 0.4, 0.4) self.frames.normalTexture:SetVertexColor(1.0, 1.0, 1.0) end end function Action:UpdateCooldown() CooldownFrame_SetTimer(self.frames.cooldown, GetActionCooldown(self.actionID)) end function Action:UpdateFlash() local action = self.actionID self:SetFlash( (IsAttackAction(action) and IsCurrentAction(action)) or IsAutoRepeatAction(action) ) end function Action:SetFlash(flash) if self.flashing ~= flash then self.flashing = flash self.flashtime = 0 if not flash then self.frames.flash:Hide() end self:UpdateCheckedState() end end function Action:RunFlash(elapsed) if self.flashing then local flashtime = self.flashtime - elapsed self.flashtime = flashtime if flashtime <= 0 then local overtime = -flashtime if overtime >= ATTACK_BUTTON_FLASH_TIME then overtime = 0 end flashtime = ATTACK_BUTTON_FLASH_TIME - overtime local flash = self.frames.flash if flash:IsShown() then flash:Hide() else flash:Show() end end end end function Action:RunRangeFinder(elapsed) local rangeTimer = self.rangeTimer if rangeTimer then rangeTimer = rangeTimer - elapsed self.rangeTimer = rangeTimer if rangeTimer <= 0 then if self.vehicleExitMode then self.frames.icon:SetVertexColor(1,1,1) elseif IsActionInRange(self.actionID) == 0 then self.frames.icon:SetVertexColor(1.0,0.1,0.1) else self:UpdateUsable() end self.rangeTimer = TOOLTIP_UPDATE_TIME end end end function Action:GetActionID(page) if page == nil then -- get the effective ID return self:GetFrame():GetAttribute("action") 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 Action:SetActionID( id, page ) id = tonumber(id) page = tonumber(page) if id == nil or id < 1 or id > 120 then ReAction:UserError(L["Action ID range is 1-120"]) return end if page and page ~= 1 then if not self.config.pageactions then self.config.pageactions = { } end self:ReleaseActionID(self.config.pageactions[page]) self.config.pageactions[page] = id self:AcquireActionID(self.config.pageactions[page]) self.frame:SetAttribute("action-page"..page,id) else self:ReleaseActionID(self.config.actionID) self.config.actionID = id self:AcquireActionID(self.config.actionID) self.frame:SetAttribute("action",id) self.frame:SetAttribute("default-action",id) if self.config.pageactions then self.config.pageactions[1] = id self.frame:SetAttribute("action-page1",id) end end end function Action:RefreshPages( force ) local nPages = self:GetBarConfig().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] = self:AcquireActionID(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"..i,c[i]) end for i = nPages+1, #c do self:ReleaseActionID(c[i]) c[i] = nil f:SetAttribute("action-page"..i,nil) end self.nPages = nPages end end function Action.SetupBarHeader( bar, config ) -- call this as a static method local f = bar:GetFrame() f:SetAttribute("mindcontrol",config.mindcontrol) f:SetAttribute("vehicle",config.vehicle) f:Execute( [[ doMindControl = self:GetAttribute("mindcontrol") doVehicle = self:GetAttribute("vehicle") control:ChildUpdate() ]]) f:SetAttribute("_onstate-mc", _onstate_mc) RegisterStateDriver(f, "mc", "[target=vehicle,exists,bonusbar:5] vehicle; [bonusbar:5] mc; none") f:SetAttribute("lockbuttons",config.lockButtons) f:SetAttribute("lockbuttonscombat",config.lockButtonsCombat) f:Execute( [[ lockButtons = self:GetAttribute("lockbuttons") lockButtonsCombat = self:GetAttribute("lockbuttonscombat") ]]) end function Action.SetButtonLock( bar, lock, lockCombat ) -- call this as a static method local f = bar:GetFrame() f:SetAttribute("lockbuttons",lock) f:SetAttribute("lockbuttonscombat",lockCombat) f:Execute( [[ lockButtons = self:GetAttribute("lockbuttons") lockButtonsCombat = self:GetAttribute("lockbuttonscombat") ]]) end function Action:ShowVehicleExit(show) self.vehicleExitMode = show and self:GetBarConfig().vehicle self:UpdateIcon() end function Action:OnEnter( ) self:SetTooltip() end function Action:OnLeave( ) GameTooltip:Hide() end function Action:OnAttributeChanged( attr, value ) self:UpdateAction() end function Action:PostClick( ) self:UpdateCheckedState() end function Action:OnUpdate( elapsed ) self:RunFlash(elapsed) self:RunRangeFinder(elapsed) end function Action:OnDragStart() self:UpdateCheckedState() self:UpdateFlash() end function Action:OnReceiveDrag() self:UpdateCheckedState() self:UpdateFlash() end function Action:OnEvent(event, ...) if self[event] then self[event](self, event, ...) end end function Action:ACTIONBAR_SLOT_CHANGED(event, action) if action == 0 or action == self.actionID then self:UpdateAll() end end function Action:PLAYER_ENTERING_WORLD() self:UpdateAction() end function Action:ACTIONBAR_PAGE_CHANGED() self:UpdateAction() end function Action:UPDATE_BONUS_ACTIONBAR() self:UpdateAction() end function Action:UPDATE_BINDINGS() self:UpdateHotkey() end function Action:PLAYER_TARGET_CHANGED() self.rangeTimer = -1 end function Action:ACTIONBAR_UPDATE_STATE() self:UpdateCheckedState() end function Action:TRADE_SKILL_SHOW() self:UpdateCheckedState() end Action.TRADE_SKILL_CLOSE = Action.TRADE_SKILL_CLOSE function Action:UNIT_ENTERED_VEHICLE(event,unit) if unit == "player" then self:UpdateCheckedState() end end Action.UNIT_EXITED_VEHICLE = Action.UNIT_ENTERED_VEHICLE function Action:COMPANION_UPDATE(event,unit) if unit == "mount" then self:UpdateCheckedState() end end function Action:ACTIONBAR_UPDATE_USABLE() self:UpdateUsable() end function Action:ACTIONBAR_UPDATE_COOLDOWN() self:UpdateCooldown() end function Action:PLAYER_ENTER_COMBAT() if IsAttackAction(self.actionID) then self:SetFlash(true) end end function Action:PLAYER_LEAVE_COMBAT() if IsAttackAction(self.actionID) then self:SetFlash(false) end end function Action:START_AUTOREPEAT_SPELL() if IsAutoRepeatAction(self.actionID) then self:SetFlash(true) end end function Action:STOP_AUTOREPEAT_SPELL() if not IsAttackAction(self.actionID) then self:SetFlash(false) end end function Action:PLAYER_REGEN_ENABLED() if self.showgridPending then self:UpdateShowGrid() end end