Mercurial > wow > reaction
view main.lua @ 11:88df7235ad8b
Version 0.33, part 2
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Tue, 20 Mar 2007 21:38:47 +0000 |
parents | f3a7bfebc283 |
children | 2735edcf9ab7 |
line wrap: on
line source
-- main.lua -- -- Top-level file for the ReAction Action Bar add-on -- -- implemented in terms of the Ace 2 development framework library: http://www.wowace.com -- -- Ace Library local object initialization local L = AceLibrary("AceLocale-2.2"):new("ReAction") local dewdrop = AceLibrary("Dewdrop-2.0") local tablet = AceLibrary("Tablet-2.0") local ReBound = AceLibrary("ReBound-1.0") -- private functions local function tcopy(t) local r = { } for k, v in pairs(t) do r[k] = (type(v) == "table" and tcopy(v) or v) end return r end -- private constants local EMPTY_BAR_SLOT = -1 -- key binding label constants BINDING_HEADER_REACTION = L["ReAction"] BINDING_NAME_REACTION_TOGGLELOCK = L["Toggle ReAction Bar Lock"] BINDING_NAME_REACTION_TOGGLEKEYBIND = L["ReAction Keybinding Mode"] -- UI panel strings REACTION_KEYBIND_TITLE = L["ReAction Keybinding"] REACTION_KEYBIND_SUBTITLE = L["Click Buttons to Set Keybindings"] REACTION_KEYBIND_DONE = L["Save"] REACTION_KEYBIND_REVERT = L["Revert"] ------------------------------ -- AceAddon setup ------------------------------ local main = AceLibrary("AceAddon-2.0"):new( "AceConsole-2.0", "AceEvent-2.0", "AceDB-2.0", "FuBarPlugin-2.0" ) function main:OnInitialize() self:RegisterChatCommand( {L["/reaction"], L["/rxn"]}, ReActionConsoleOptions, "REACTION" ) self:RegisterDB("ReActionDB","ReActionDBPC") self:RegisterDefaults("profile", ReAction_DefaultProfile) self:RegisterEvent("PLAYER_REGEN_DISABLED","CombatLockdown") self:RegisterEvent("PLAYER_ENTERING_WORLD","HideDefaultBars") self:DisableDefaultKeybindings() -- initial non-persistent state self.locked = true self.bars = { } end -- OnEnable is called at startup (startup = true, oldConfig = nil), -- and when the profile is changed (startup = false, oldConfig ~= nil ) function main:OnEnable( startup, oldConfig ) if self.db.profile.firstRunDone ~= true then self.db.profile.bars = tcopy(ReAction_DefaultBlizzardBars) end self:DestroyAllBars() self:SetupBars() self:UpgradeProfile() self:SetupKeybindings( oldConfig and oldConfig.bindings ) if self.db.profile.firstRunDone ~= true then self:Unlock() end self.db.profile.firstRunDone = true end function main:OnDisable() self:Lock() end -- OnProfileEnable() is only called when switching profiles, NOT for the initial profile at load time. function main:OnProfileEnable( oldName, oldData ) self:OnEnable(false, oldData) end function main:UpgradeProfile() if self.db.profile.firstRunDone ~= true and #self.db.profile.bindings == 0 then for _, bar in pairs(self.bars) do for _, button in pairs(bar.buttons) do local key = ReBound:GetBinding(button:GetActionFrame(),"LeftButton") if key and #key > 0 and not self.db.profile.bindings[key] then self:REBOUND_BIND(key,button:GetActionFrame():GetName(),"LeftButton") end end end end end -------------------------------------------- -- FuBar plugin setup -- Even if FuBar isn't installed, the plugin -- provides a nice minimap-button interface. --------------------------------------------- main.hasIcon = "Interface\\Icons\\INV_Qiraj_JewelEncased" main.hasNoColor = true main.hideMenuTitle = true main.defaultPosition = "LEFT" main.defaultMinimapPosition = 240 -- degrees main.OnMenuRequest = tcopy(ReActionGlobalMenuOptions) -- use a copy, or bar menus will have FuBar inserted items main.independentProfile = true -- set the handler for the global bar menu options -- have to do this after tcopy() above, otherwise it will try to copy the handler object (bad idea) ReActionGlobalMenuOptions.handler = main function main:OnTooltipUpdate() local c = tablet:AddCategory("columns", 2) c:AddLine("text", L["Bar lock"], "text2", self.locked and ("|cffff0000"..L["Locked"].."|r") or ("|cffffcc00"..L["Unlocked"].."|r")) c:AddLine("text", L["Button lock"], "text2", LOCK_ACTIONBAR == "1" and ("|cffcc0000"..L["Locked"].."|r") or ("|cff00cc00"..L["Unlocked"].."|r")) c:AddLine("text", L["Kebinding mode"], "text2", self:GetKeybindMode() and ("|cff33ff33"..L["On"].."|r") or ("|cffffcc00"..L["Off"].."|r")) tablet:SetHint(L["|cffffcc00Shift-Click for bar lock|n|cff33ff33Alt-Click|r for keybindings|nRight-click for menu"]) end function main:OnClick(button) if IsShiftKeyDown() then self:ToggleLocked() self:UpdateDisplay() elseif IsAltKeyDown() then self:ToggleKeybindMode() self:UpdateDisplay() end end ------------------------------ -- Key binding functions ------------------------------ function main:DisableDefaultKeybindings() -- change the labels on all actionbar keybindings in the default -- interface. local label = "|cff999999("..L["Use ReAction"]..")|r" for i = 1, 12 do setglobal("BINDING_NAME_ACTIONBUTTON"..i,label) for j = 1, 4 do setglobal("BINDING_NAME_MULTIACTIONBAR"..j.."BUTTON"..i,label) end end for i = 1, 6 do setglobal("BINDING_NAME_ACTIONPAGE"..i,label) end for i = 1, 10 do setglobal("BINDING_NAME_BONUSACTIONBUTTON"..i,label) setglobal("BINDING_NAME_SHAPESHIFTBUTTON"..i,label) end BINDING_HEADER_ACTIONBAR = "|cff999999"..L["Action Bar Functions Disabled"].."|r" BINDING_HEADER_MULTIACTIONBAR = "|cff999999"..L["Multi-Action Bar Functions Disabled"].."|r" BINDING_NAME_NEXTACTIONPAGE = label BINDING_NAME_PREVIOUSACTIONPAGE = label end function main:SetupKeybindings( previous ) if previous then self:UnregisterEvent("REBOUND_BIND") self:UnregisterEvent("REBOUND_UNBIND") for key, binding in pairs(previous) do ReBound:ClearBinding(key, getglobal(binding.target), binding.button, true) end end if self.db.profile.firstRunDone ~= true then self:StealKeyBindings() else for key, binding in pairs(self.db.profile.bindings) do ReBound:SetBinding(key, getglobal(binding.target), binding.button) end end SaveBindings(GetCurrentBindingSet()) self:RegisterEvent("REBOUND_BIND") self:RegisterEvent("REBOUND_UNBIND") end function main:StealKeyBindings() -- steal the keybindings of the main action bar and assign them to rebar 1, buttons 1-12 for i = 1, 12 do local key = GetBindingKey("ACTIONBUTTON"..i) if key and #key > 0 then ReBound:ClearBinding(key,nil,nil,true) -- suppress notification printouts ReBound:SetBinding(key, self.bars[1].buttons[i]:GetActionFrame(), "LeftButton") end end SaveBindings(GetCurrentBindingSet()) end function main:REBOUND_BIND(key, target, button) if key and target then self.db.profile.bindings[key] = { target = target, button = button } end end function main:REBOUND_UNBIND(key) if key then self.db.profile.bindings[key] = nil end end function main:ToggleKeybindMode() self:SetKeybindMode(not self:GetKeybindMode()) end function main:GetKeybindMode() return self.keybindMode end function main:SetKeybindMode(enabled) if not InCombatLockdown() then self.keybindMode = enabled for _, bar in pairs(self.bars) do for __, button in pairs(bar.buttons) do if button and button ~= EMPTY_BAR_SLOT then button:TempShow(enabled) end end end if enabled then ReBound:ShowAll() ReActionKeybindDialog:Show() else ReBound:HideAll() if ReActionKeybindDialog:IsShown() then ReActionKeybindDialog:Hide() end end else UIErrorsFrame:AddMessage(ERROR_NOT_IN_COMBAT) end end ---------------------------- -- Bar lock/unlock functions ---------------------------- function main:CombatLockdown() if not self:IsLocked() then self:Lock() UIErrorsFrame:AddMessage(L["ReAction bars locked when in combat"]) end ReActionKeybindDialog:Hide() end function main:SetLocked( lock ) if lock ~= self.locked then if not lock and InCombatLockdown() then UIErrorsFrame:AddMessage(ERROR_NOT_IN_COMBAT) else self.locked = lock and true or false -- force data integrity for _, bar in pairs(self.bars) do if bar ~= EMPTY_BAR_SLOT then if self.locked then bar:HideControls() -- close any dewdrop menu owned by the bar if bar:GetControlFrame() == dewdrop:GetOpenedParent() then dewdrop:Close() end else bar:ShowControls() end end end end end end function main:IsLocked() return self.locked end function main:Lock() self:SetLocked(true) end function main:Unlock() self:SetLocked(false) end function main:ToggleLocked() main:SetLocked( not(self.locked) ) end -------------------------------------------------------- -- Functions to hide the default Blizzard main bar parts -------------------------------------------------------- function main:HideArt() if self.db.profile.hideArt then -- the pet bar is a child of MainMenuBar, and can't be hidden. Need to reparent it PetActionBarFrame:SetParent(UIParent) MainMenuBar:Hide() -- this also hides the bags, xp bar, lag meter, and micro menu buttons. -- these two are the pet bar background -- unfortunately UIParent_ManageFramePositions() shows and hides these too -- so they get reparented to MainMenuBar SlidingActionBarTexture0:SetParent(MainMenuBar) SlidingActionBarTexture1:SetParent(MainMenuBar) else SlidingActionBarTexture0:SetParent(PetActionBarFrame) SlidingActionBarTexture1:SetParent(PetActionBarFrame) MainMenuBar:Show() end end function main:IsArtHidden() return self.db.profile.hideArt end function main:SetHideArt( hide ) if InCombatLockdown() then UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT) else self.db.profile.hideArt = hide and true or false -- force data integrity self:HideArt() end end function main:ToggleHideArt() self:SetHideArt( not self:IsArtHidden() ) end -- Hide default Blizzard bars local blizzDefaultBars = { ActionButton1, ActionButton2, ActionButton3, ActionButton4, ActionButton5, ActionButton6, ActionButton7, ActionButton8, ActionButton9, ActionButton10, ActionButton11, ActionButton12, PetActionButton1, PetActionButton2, PetActionButton3, PetActionButton4, PetActionButton5, PetActionButton6, PetActionButton7, PetActionButton8, PetActionButton9, PetActionButton10, -- NOT the PetActionBarFrame, though - we need that to auto-hide/show our pet action bars MainMenuBarPageNumber, ActionBarUpButton, ActionBarDownButton, BonusActionBarFrame, ShapeshiftBarFrame, MultiBarLeft, MultiBarRight, MultiBarBottomLeft, MultiBarBottomRight, } local function disableUIOptions() -- disable the buttons to hide/show the blizzard multiaction bars -- see UIOptionsFrame.lua and .xml -- This is called every time the options panel is shown, after it is set up for _, idx in pairs( { 33, 34, 35, 36, 37, 40 } ) do local f = getglobal("UIOptionsFrameCheckButton"..idx) f.disabled = true OptionsFrame_DisableCheckBox(f) f:SetChecked(false) end end function main:HideDefaultBars() for _, f in pairs(blizzDefaultBars) do f:Hide() f:ClearAllPoints() f:SetParent(ReAction.recycler) f:SetPoint("TOPLEFT") end MainMenuBar:SetFrameStrata("LOW") -- otherwise it appears on top of bars, if it isn't hidden hooksecurefunc("UIOptionsFrame_Load",disableUIOptions) end --------------------------------------- -- Bar setup and manipulation functions --------------------------------------- -- Reset bars to blizzard defaults function main:ResetBars() if InCombatLockdown() then UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT) else self:DestroyAllBars() self.db.profile.bars = tcopy(ReAction_DefaultBlizzardBars) self:SetupBars() end end function main:DestroyAllBars() -- destroy any existing bars for id = 1, table.maxn(self.bars) do self:DestroyBar(id) end end function main:SetupBars() -- hide the default Blizzard art, if configued self:HideArt() -- set up the bars from the profile -- note the use of table.maxn rather than # or ipairs: -- our array of bars can in fact contain holes for id = 1, table.maxn(self.db.profile.bars) do local config = self.db.profile.bars[id] if config then self:CreateBar(config, id) end end -- anchor the bars, have to do this in a second pass because -- they might be anchored to each other in a non-ordered way for _, bar in pairs(self.bars) do if bar ~= EMPTY_BAR_SLOT then bar:ApplyAnchor() end end end function main:CreateBar( config, id ) local bar = ReBar:new(config, id) local buttonType = ReAction:GetButtonType(config.btnConfig.subtype) if buttonType then self.bars[id] = bar self.db.profile.bars[id] = config -- initialize dewdrop menu local cf = bar:GetControlFrame() dewdrop:Register(cf, 'children', function() dewdrop:FeedAceOptionsTable(ReActionGlobalMenuOptions) dewdrop:FeedAceOptionsTable(GenerateReActionBarOptions(bar,self)) dewdrop:FeedAceOptionsTable(buttonType:GenerateOptionsTable(config.btnConfig, function() return bar:GetButtonList() end)) end, 'cursorX', true, 'cursorY', true ) bar:GetControlFrame():SetScript("OnClick", function(btn) if btn == "RightButton" then dewdrop:Open(cf) end end ) if not self.locked then bar:ShowControls() end return bar else if bar then bar:Destroy() end error(L["Tried to create a button of unknown type"]) end end function main:DestroyBar( id ) local bar = self.bars[id] if bar and bar ~= EMPTY_BAR_SLOT then local cf = bar:GetControlFrame() if cf == dewdrop:GetOpenedParent() then dewdrop:Close() dewdrop:Unregister(cf) end bar:Destroy() -- we can't do tremove because each bar ID is encoded into the -- frame names as they're created. Need a blank entry in the table. -- The nice thing is that table.insert in NewBar() will automatically -- find the lowest numbered nil slot. self.bars[id] = EMPTY_BAR_SLOT end end -- -- this function is a wrapper for CreateBar() which looks up the bar type -- and constructs a new configuration object of the right type. function main:NewBar( type ) if InCombatLockdown() then UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT) else local t = ReAction:GetButtonType(type) if t then local c = tcopy(ReAction_DefaultBarConfig["ReAction"][type]) local id = nil for i = 1, table.maxn(self.bars) + 1 do -- there may be holes, so #self.bars won't work if self.bars[i] == nil or self.bars[i] == EMPTY_BAR_SLOT then id = i break end end local bar = self:CreateBar(c, id) bar:ApplyAnchor() self:Unlock() end end end -- -- This function is a wrapper for DestroyBar() which does in-combat -- checking and updates the config. function main:DeleteBar(id) if InCombatLockdown() then UIErrorsFrame:AddMessage(SPELL_FAILED_AFFECTING_COMBAT) else if self.bars[id] then self:DestroyBar(id) self.db.profile.bars[id] = nil end end end ----------------- -- General utility ----------------- function main:ToggleIds() if self.showIds then ReAction:HideAllIds() else ReAction:ShowAllIds() end self.showIds = not self.showIds end function main:AreIdsVisible() return self.showIds end -- set a global variable for Bindings.xml ReActionAddOn = main