PageRenderTime 100ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/FrameXML/UIParent.lua

https://bitbucket.org/Shenton/world-of-warcraft-user-interface-source
Lua | 4154 lines | 3357 code | 457 blank | 340 comment | 780 complexity | 8b04045c69f56a874f0429384d39f43e MD5 | raw file
  1. TOOLTIP_UPDATE_TIME = 0.2;
  2. ROTATIONS_PER_SECOND = .5;
  3. BOSS_FRAME_CASTBAR_HEIGHT = 16;
  4. -- Alpha animation stuff
  5. FADEFRAMES = {};
  6. FLASHFRAMES = {};
  7. -- Pulsing stuff
  8. PULSEBUTTONS = {};
  9. -- Shine animation
  10. SHINES_TO_ANIMATE = {};
  11. -- Per panel settings
  12. UIPanelWindows = {};
  13. --Center Menu Frames
  14. UIPanelWindows["GameMenuFrame"] = { area = "center", pushable = 0, whileDead = 1 };
  15. UIPanelWindows["VideoOptionsFrame"] = { area = "center", pushable = 0, whileDead = 1 };
  16. UIPanelWindows["AudioOptionsFrame"] = { area = "center", pushable = 0, whileDead = 1 };
  17. UIPanelWindows["InterfaceOptionsFrame"] = { area = "center", pushable = 0, whileDead = 1 };
  18. UIPanelWindows["HelpFrame"] = { area = "center", pushable = 0, whileDead = 1 };
  19. -- Frames using the new Templates
  20. UIPanelWindows["CharacterFrame"] = { area = "left", pushable = 3, whileDead = 1};
  21. UIPanelWindows["SpellBookFrame"] = { area = "left", pushable = 1, whileDead = 1, width = 575, height = 545 };
  22. UIPanelWindows["TaxiFrame"] = { area = "left", pushable = 0, width = 605, height = 580 };
  23. UIPanelWindows["PVPUIFrame"] = { area = "left", pushable = 0, whileDead = 1, width = 563};
  24. UIPanelWindows["PVPBannerFrame"] = { area = "left", pushable = 1};
  25. UIPanelWindows["PetStableFrame"] = { area = "left", pushable = 0};
  26. UIPanelWindows["PVEFrame"] = { area = "left", pushable = 0, whileDead = 1, width = 563};
  27. UIPanelWindows["EncounterJournal"] = { area = "left", pushable = 0, whileDead = 1, width = 830};
  28. UIPanelWindows["PetJournalParent"] = { area = "left", pushable = 0, whileDead = 1, width = 830};
  29. UIPanelWindows["TradeFrame"] = { area = "left", pushable = 1};
  30. UIPanelWindows["LootFrame"] = { area = "left", pushable = 7};
  31. UIPanelWindows["MerchantFrame"] = { area = "left", pushable = 0};
  32. UIPanelWindows["TabardFrame"] = { area = "left", pushable = 0};
  33. UIPanelWindows["PVPBannerFrame"] = { area = "left", pushable = 1};
  34. UIPanelWindows["MailFrame"] = { area = "left", pushable = 0};
  35. UIPanelWindows["BankFrame"] = { area = "left", pushable = 6, width = 425 };
  36. UIPanelWindows["QuestLogFrame"] = { area = "doublewide", pushable = 0, whileDead = 1 };
  37. UIPanelWindows["QuestLogDetailFrame"] = { area = "left", pushable = 1, whileDead = 1 };
  38. UIPanelWindows["QuestFrame"] = { area = "left", pushable = 0};
  39. UIPanelWindows["GuildRegistrarFrame"] = { area = "left", pushable = 0};
  40. UIPanelWindows["GossipFrame"] = { area = "left", pushable = 0};
  41. UIPanelWindows["DressUpFrame"] = { area = "left", pushable = 2};
  42. UIPanelWindows["PetitionFrame"] = { area = "left", pushable = 0};
  43. UIPanelWindows["ItemTextFrame"] = { area = "left", pushable = 0};
  44. UIPanelWindows["FriendsFrame"] = { area = "left", pushable = 0, whileDead = 1, extraWidth = 32};
  45. UIPanelWindows["RaidParentFrame"] = { area = "left", pushable = 1, whileDead = 1 };
  46. UIPanelWindows["RaidBrowserFrame"] = { area = "left", pushable = 1, };
  47. -- Frames NOT using the new Templates
  48. UIPanelWindows["WorldMapFrame"] = { area = "full", pushable = 0, xoffset = -16, yoffset = 12, whileDead = 1 };
  49. UIPanelWindows["CinematicFrame"] = { area = "full", pushable = 0, xoffset = -16, yoffset = 12, whileDead = 1 };
  50. UIPanelWindows["ChatConfigFrame"] = { area = "center", pushable = 0, xoffset = -16, yoffset = 12, whileDead = 1 };
  51. UIPanelWindows["WorldStateScoreFrame"] = { area = "center", pushable = 0, xoffset = -16, yoffset = 12, whileDead = 1 };
  52. UIPanelWindows["QuestChoiceFrame"] = { area = "center", pushable = 0, xoffset = -16, yoffset = 12, whileDead = 0, allowOtherPanels = 1 };
  53. local function GetUIPanelWindowInfo(frame, name)
  54. if ( not frame:GetAttribute("UIPanelLayout-defined") ) then
  55. local info = UIPanelWindows[frame:GetName()];
  56. if ( not info ) then
  57. return;
  58. end
  59. frame:SetAttribute("UIPanelLayout-defined", true);
  60. for name,value in pairs(info) do
  61. frame:SetAttribute("UIPanelLayout-"..name, value);
  62. end
  63. end
  64. return frame:GetAttribute("UIPanelLayout-"..name);
  65. end
  66. function SetUIPanelAttribute(frame, name, value)
  67. local info = UIPanelWindows[frame:GetName()];
  68. if ( not info ) then
  69. return;
  70. end
  71. if ( not frame:GetAttribute("UIPanelLayout-defined") ) then
  72. frame:SetAttribute("UIPanelLayout-defined", true);
  73. for name,value in pairs(info) do
  74. frame:SetAttribute("UIPanelLayout-"..name, value);
  75. end
  76. end
  77. frame:SetAttribute("UIPanelLayout-"..name, value);
  78. end
  79. -- These are windows that rely on a parent frame to be open. If the parent closes or a pushable frame overlaps them they must be hidden.
  80. UIChildWindows = {
  81. "OpenMailFrame",
  82. "GuildControlUI",
  83. "GuildMemberDetailFrame",
  84. "TokenFramePopup",
  85. "GuildBankPopupFrame",
  86. "GearManagerDialog",
  87. };
  88. UISpecialFrames = {
  89. "ItemRefTooltip",
  90. "ColorPickerFrame",
  91. "ScrollOfResurrectionFrame",
  92. "ScrollOfResurrectionSelectionFrame"
  93. };
  94. UIMenus = {
  95. "ChatMenu",
  96. "EmoteMenu",
  97. "LanguageMenu",
  98. "DropDownList1",
  99. "DropDownList2",
  100. };
  101. NUM_ITEM_QUALITIES = 7;
  102. ITEM_QUALITY_COLORS = { };
  103. for i = -1, NUM_ITEM_QUALITIES do
  104. ITEM_QUALITY_COLORS[i] = { };
  105. ITEM_QUALITY_COLORS[i].r,
  106. ITEM_QUALITY_COLORS[i].g,
  107. ITEM_QUALITY_COLORS[i].b,
  108. ITEM_QUALITY_COLORS[i].hex = GetItemQualityColor(i);
  109. ITEM_QUALITY_COLORS[i].hex = "|c"..ITEM_QUALITY_COLORS[i].hex;
  110. end
  111. function UIParent_OnLoad(self)
  112. self:RegisterEvent("PLAYER_LOGIN");
  113. self:RegisterEvent("PLAYER_DEAD");
  114. self:RegisterEvent("SELF_RES_SPELL_CHANGED");
  115. self:RegisterEvent("PLAYER_ALIVE");
  116. self:RegisterEvent("PLAYER_UNGHOST");
  117. self:RegisterEvent("RESURRECT_REQUEST");
  118. self:RegisterEvent("PLAYER_SKINNED");
  119. self:RegisterEvent("TRADE_REQUEST");
  120. self:RegisterEvent("CHANNEL_INVITE_REQUEST");
  121. self:RegisterEvent("CHANNEL_PASSWORD_REQUEST");
  122. self:RegisterEvent("PARTY_INVITE_REQUEST");
  123. self:RegisterEvent("PARTY_INVITE_CANCEL");
  124. self:RegisterEvent("GUILD_INVITE_REQUEST");
  125. self:RegisterEvent("GUILD_INVITE_CANCEL");
  126. self:RegisterEvent("ARENA_TEAM_INVITE_REQUEST");
  127. self:RegisterEvent("PLAYER_CAMPING");
  128. self:RegisterEvent("PLAYER_QUITING");
  129. self:RegisterEvent("LOGOUT_CANCEL");
  130. self:RegisterEvent("LOOT_BIND_CONFIRM");
  131. self:RegisterEvent("EQUIP_BIND_CONFIRM");
  132. self:RegisterEvent("AUTOEQUIP_BIND_CONFIRM");
  133. self:RegisterEvent("USE_BIND_CONFIRM");
  134. self:RegisterEvent("CONFIRM_BEFORE_USE");
  135. self:RegisterEvent("DELETE_ITEM_CONFIRM");
  136. self:RegisterEvent("QUEST_ACCEPT_CONFIRM");
  137. self:RegisterEvent("QUEST_LOG_UPDATE");
  138. self:RegisterEvent("UNIT_QUEST_LOG_CHANGED");
  139. self:RegisterEvent("CURSOR_UPDATE");
  140. self:RegisterEvent("LOCALPLAYER_PET_RENAMED");
  141. self:RegisterEvent("PLAYER_ENTERING_WORLD");
  142. self:RegisterEvent("MIRROR_TIMER_START");
  143. self:RegisterEvent("DUEL_REQUESTED");
  144. self:RegisterEvent("DUEL_OUTOFBOUNDS");
  145. self:RegisterEvent("DUEL_INBOUNDS");
  146. self:RegisterEvent("DUEL_FINISHED");
  147. self:RegisterEvent("PET_BATTLE_PVP_DUEL_REQUESTED");
  148. self:RegisterEvent("PET_BATTLE_QUEUE_PROPOSE_MATCH");
  149. self:RegisterEvent("PET_BATTLE_QUEUE_PROPOSAL_DECLINED");
  150. self:RegisterEvent("PET_BATTLE_QUEUE_PROPOSAL_ACCEPTED");
  151. self:RegisterEvent("PET_BATTLE_PVP_DUEL_REQUEST_CANCEL");
  152. self:RegisterEvent("TRADE_REQUEST_CANCEL");
  153. self:RegisterEvent("CONFIRM_XP_LOSS");
  154. self:RegisterEvent("CORPSE_IN_RANGE");
  155. self:RegisterEvent("CORPSE_IN_INSTANCE");
  156. self:RegisterEvent("CORPSE_OUT_OF_RANGE");
  157. self:RegisterEvent("AREA_SPIRIT_HEALER_IN_RANGE");
  158. self:RegisterEvent("AREA_SPIRIT_HEALER_OUT_OF_RANGE");
  159. self:RegisterEvent("BIND_ENCHANT");
  160. self:RegisterEvent("REPLACE_ENCHANT");
  161. self:RegisterEvent("TRADE_REPLACE_ENCHANT");
  162. self:RegisterEvent("END_BOUND_TRADEABLE");
  163. self:RegisterEvent("CURRENT_SPELL_CAST_CHANGED");
  164. self:RegisterEvent("MACRO_ACTION_BLOCKED");
  165. self:RegisterEvent("ADDON_ACTION_BLOCKED");
  166. self:RegisterEvent("MACRO_ACTION_FORBIDDEN");
  167. self:RegisterEvent("ADDON_ACTION_FORBIDDEN");
  168. self:RegisterEvent("PLAYER_CONTROL_LOST");
  169. self:RegisterEvent("PLAYER_CONTROL_GAINED");
  170. self:RegisterEvent("START_LOOT_ROLL");
  171. self:RegisterEvent("CONFIRM_LOOT_ROLL");
  172. self:RegisterEvent("CONFIRM_DISENCHANT_ROLL");
  173. self:RegisterEvent("INSTANCE_BOOT_START");
  174. self:RegisterEvent("INSTANCE_BOOT_STOP");
  175. self:RegisterEvent("INSTANCE_LOCK_START");
  176. self:RegisterEvent("INSTANCE_LOCK_STOP");
  177. self:RegisterEvent("INSTANCE_LOCK_WARNING");
  178. self:RegisterEvent("CONFIRM_TALENT_WIPE");
  179. self:RegisterEvent("CONFIRM_BINDER");
  180. self:RegisterEvent("CONFIRM_SUMMON");
  181. self:RegisterEvent("CANCEL_SUMMON");
  182. self:RegisterEvent("GOSSIP_CONFIRM");
  183. self:RegisterEvent("GOSSIP_CONFIRM_CANCEL");
  184. self:RegisterEvent("GOSSIP_ENTER_CODE");
  185. self:RegisterEvent("GOSSIP_CLOSED");
  186. self:RegisterEvent("BILLING_NAG_DIALOG");
  187. self:RegisterEvent("IGR_BILLING_NAG_DIALOG");
  188. self:RegisterEvent("VARIABLES_LOADED");
  189. self:RegisterEvent("GROUP_ROSTER_UPDATE");
  190. self:RegisterEvent("RAID_INSTANCE_WELCOME");
  191. self:RegisterEvent("LEVEL_GRANT_PROPOSED");
  192. self:RegisterEvent("RAISED_AS_GHOUL");
  193. self:RegisterEvent("SOR_START_EXPERIENCE_INCOMPLETE");
  194. self:RegisterEvent("MISSING_OUT_ON_LOOT");
  195. self:RegisterEvent("SPELL_CONFIRMATION_PROMPT");
  196. self:RegisterEvent("SPELL_CONFIRMATION_TIMEOUT");
  197. -- Events for auction UI handling
  198. self:RegisterEvent("AUCTION_HOUSE_SHOW");
  199. self:RegisterEvent("AUCTION_HOUSE_CLOSED");
  200. self:RegisterEvent("AUCTION_HOUSE_DISABLED");
  201. -- Events for trainer UI handling
  202. self:RegisterEvent("TRAINER_SHOW");
  203. self:RegisterEvent("TRAINER_CLOSED");
  204. -- Events for trade skill UI handling
  205. self:RegisterEvent("TRADE_SKILL_SHOW");
  206. self:RegisterEvent("TRADE_SKILL_CLOSE");
  207. -- Events for Item socketing UI
  208. self:RegisterEvent("SOCKET_INFO_UPDATE");
  209. -- Events for taxi benchmarking
  210. self:RegisterEvent("ENABLE_TAXI_BENCHMARK");
  211. self:RegisterEvent("DISABLE_TAXI_BENCHMARK");
  212. -- Push to talk
  213. self:RegisterEvent("VOICE_PUSH_TO_TALK_START");
  214. self:RegisterEvent("VOICE_PUSH_TO_TALK_STOP");
  215. -- Events for BarberShop Handling
  216. self:RegisterEvent("BARBER_SHOP_OPEN");
  217. self:RegisterEvent("BARBER_SHOP_CLOSE");
  218. -- Events for Guild bank UI
  219. self:RegisterEvent("GUILDBANKFRAME_OPENED");
  220. self:RegisterEvent("GUILDBANKFRAME_CLOSED");
  221. -- Events for Achievements!
  222. self:RegisterEvent("ACHIEVEMENT_EARNED");
  223. --Events for GMChatUI
  224. self:RegisterEvent("CHAT_MSG_WHISPER");
  225. -- Events for WoW Mouse
  226. self:RegisterEvent("WOW_MOUSE_NOT_FOUND");
  227. -- Events for talent wipes
  228. self:RegisterEvent("TALENTS_INVOLUNTARILY_RESET");
  229. -- Events for reforging
  230. self:RegisterEvent("FORGE_MASTER_OPENED");
  231. self:RegisterEvent("FORGE_MASTER_CLOSED");
  232. -- Events for Archaeology
  233. self:RegisterEvent("ARCHAEOLOGY_TOGGLE");
  234. -- Events for transmogrify
  235. self:RegisterEvent("TRANSMOGRIFY_OPEN");
  236. self:RegisterEvent("TRANSMOGRIFY_CLOSE");
  237. -- Events for void storage
  238. self:RegisterEvent("VOID_STORAGE_OPEN");
  239. self:RegisterEvent("VOID_STORAGE_CLOSE");
  240. -- Events for Trial caps
  241. self:RegisterEvent("TRIAL_CAP_REACHED_MONEY");
  242. self:RegisterEvent("TRIAL_CAP_REACHED_LEVEL");
  243. -- Events for black market
  244. self:RegisterEvent("BLACK_MARKET_OPEN");
  245. self:RegisterEvent("BLACK_MARKET_CLOSE");
  246. -- Events for item upgrades
  247. self:RegisterEvent("ITEM_UPGRADE_MASTER_OPENED");
  248. self:RegisterEvent("ITEM_UPGRADE_MASTER_CLOSED");
  249. -- Events for Pet Jornal
  250. self:RegisterEvent("PET_JOURNAL_NEW_BATTLE_SLOT");
  251. -- Events for Quest Choice
  252. self:RegisterEvent("QUEST_CHOICE_UPDATE");
  253. end
  254. -- Addons --
  255. local FailedAddOnLoad = {};
  256. function UIParentLoadAddOn(name)
  257. local loaded, reason = LoadAddOn(name);
  258. if ( not loaded ) then
  259. if ( not FailedAddOnLoad[name] ) then
  260. message(format(ADDON_LOAD_FAILED, name, _G["ADDON_"..reason]));
  261. FailedAddOnLoad[name] = true;
  262. end
  263. end
  264. return loaded;
  265. end
  266. function AuctionFrame_LoadUI()
  267. UIParentLoadAddOn("Blizzard_AuctionUI");
  268. end
  269. function BattlefieldMinimap_LoadUI()
  270. UIParentLoadAddOn("Blizzard_BattlefieldMinimap");
  271. end
  272. function ClassTrainerFrame_LoadUI()
  273. UIParentLoadAddOn("Blizzard_TrainerUI");
  274. end
  275. function CombatLog_LoadUI()
  276. UIParentLoadAddOn("Blizzard_CombatLog");
  277. end
  278. function GuildBankFrame_LoadUI()
  279. UIParentLoadAddOn("Blizzard_GuildBankUI");
  280. end
  281. function InspectFrame_LoadUI()
  282. UIParentLoadAddOn("Blizzard_InspectUI");
  283. end
  284. function KeyBindingFrame_LoadUI()
  285. UIParentLoadAddOn("Blizzard_BindingUI");
  286. end
  287. function MacroFrame_LoadUI()
  288. UIParentLoadAddOn("Blizzard_MacroUI");
  289. end
  290. function MacroFrame_SaveMacro()
  291. -- this will be overwritten with the real thing when the addon is loaded
  292. end
  293. function RaidFrame_LoadUI()
  294. UIParentLoadAddOn("Blizzard_RaidUI");
  295. end
  296. function TalentFrame_LoadUI()
  297. UIParentLoadAddOn("Blizzard_TalentUI");
  298. end
  299. function TradeSkillFrame_LoadUI()
  300. UIParentLoadAddOn("Blizzard_TradeSkillUI");
  301. end
  302. function GMSurveyFrame_LoadUI()
  303. UIParentLoadAddOn("Blizzard_GMSurveyUI");
  304. end
  305. function ItemSocketingFrame_LoadUI()
  306. UIParentLoadAddOn("Blizzard_ItemSocketingUI");
  307. end
  308. function BarberShopFrame_LoadUI()
  309. UIParentLoadAddOn("Blizzard_BarberShopUI");
  310. end
  311. function AchievementFrame_LoadUI()
  312. UIParentLoadAddOn("Blizzard_AchievementUI");
  313. end
  314. function TimeManager_LoadUI()
  315. UIParentLoadAddOn("Blizzard_TimeManager");
  316. end
  317. function TokenFrame_LoadUI()
  318. UIParentLoadAddOn("Blizzard_TokenUI");
  319. end
  320. function GlyphFrame_LoadUI()
  321. UIParentLoadAddOn("Blizzard_GlyphUI");
  322. end
  323. function Calendar_LoadUI()
  324. UIParentLoadAddOn("Blizzard_Calendar");
  325. end
  326. function Reforging_LoadUI()
  327. UIParentLoadAddOn("Blizzard_ReforgingUI");
  328. end
  329. function ItemAlteration_LoadUI()
  330. UIParentLoadAddOn("Blizzard_ItemAlterationUI");
  331. end
  332. function VoidStorage_LoadUI()
  333. UIParentLoadAddOn("Blizzard_VoidStorageUI");
  334. end
  335. function ArchaeologyFrame_LoadUI()
  336. UIParentLoadAddOn("Blizzard_ArchaeologyUI");
  337. end
  338. function GMChatFrame_LoadUI(...)
  339. if ( IsAddOnLoaded("Blizzard_GMChatUI") ) then
  340. return;
  341. else
  342. UIParentLoadAddOn("Blizzard_GMChatUI");
  343. if ( select(1, ...) ) then
  344. GMChatFrame_OnEvent(GMChatFrame, ...);
  345. end
  346. end
  347. end
  348. function Arena_LoadUI()
  349. UIParentLoadAddOn("Blizzard_ArenaUI");
  350. end
  351. function GuildFrame_LoadUI()
  352. UIParentLoadAddOn("Blizzard_GuildUI");
  353. end
  354. function LookingForGuildFrame_LoadUI()
  355. UIParentLoadAddOn("Blizzard_LookingForGuildUI");
  356. end
  357. function EncounterJournal_LoadUI()
  358. UIParentLoadAddOn("Blizzard_EncounterJournal");
  359. end
  360. function PetJournal_LoadUI()
  361. UIParentLoadAddOn("Blizzard_PetJournal");
  362. end
  363. function BlackMarket_LoadUI()
  364. UIParentLoadAddOn("Blizzard_BlackMarketUI");
  365. end
  366. function ItemUpgrade_LoadUI()
  367. UIParentLoadAddOn("Blizzard_ItemUpgradeUI");
  368. end
  369. function PVP_LoadUI()
  370. UIParentLoadAddOn("Blizzard_PVPUI");
  371. end
  372. function QuestChoice_LoadUI()
  373. UIParentLoadAddOn("Blizzard_QuestChoice");
  374. end
  375. --[[
  376. function MovePad_LoadUI()
  377. UIParentLoadAddOn("Blizzard_MovePad");
  378. end
  379. ]]
  380. function ShowMacroFrame()
  381. MacroFrame_LoadUI();
  382. if ( MacroFrame_Show ) then
  383. MacroFrame_Show();
  384. end
  385. end
  386. function InspectAchievements (unit)
  387. if (IsBlizzCon()) then
  388. return;
  389. end
  390. AchievementFrame_LoadUI();
  391. AchievementFrame_DisplayComparison(unit);
  392. end
  393. function ToggleAchievementFrame(stats)
  394. if ( ( HasCompletedAnyAchievement() or IsInGuild() ) and CanShowAchievementUI() ) then
  395. AchievementFrame_LoadUI();
  396. AchievementFrame_ToggleAchievementFrame(stats);
  397. end
  398. end
  399. function ToggleTalentFrame()
  400. if (IsBlizzCon() or (UnitLevel("player") < SHOW_SPEC_LEVEL)) then
  401. return;
  402. end
  403. TalentFrame_LoadUI();
  404. if ( PlayerTalentFrame_Toggle ) then
  405. PlayerTalentFrame_Toggle(GetActiveSpecGroup());
  406. end
  407. end
  408. function ToggleGlyphFrame()
  409. if (IsBlizzCon()) then
  410. return;
  411. end
  412. if ( UnitLevel("player") < SHOW_INSCRIPTION_LEVEL ) then
  413. return;
  414. end
  415. GlyphFrame_LoadUI();
  416. if ( GlyphFrame_Toggle ) then
  417. GlyphFrame_Toggle();
  418. end
  419. end
  420. function OpenGlyphFrame()
  421. if (IsBlizzCon()) then
  422. return;
  423. end
  424. if ( UnitLevel("player") < SHOW_INSCRIPTION_LEVEL ) then
  425. return;
  426. end
  427. GlyphFrame_LoadUI();
  428. if ( GlyphFrame_Open ) then
  429. GlyphFrame_Open();
  430. end
  431. end
  432. function ToggleBattlefieldMinimap()
  433. BattlefieldMinimap_LoadUI();
  434. if ( BattlefieldMinimap_Toggle ) then
  435. BattlefieldMinimap_Toggle();
  436. end
  437. end
  438. function ToggleTimeManager()
  439. TimeManager_LoadUI();
  440. if ( TimeManager_Toggle ) then
  441. TimeManager_Toggle();
  442. end
  443. end
  444. function ToggleCalendar()
  445. if (IsBlizzCon()) then
  446. return;
  447. end
  448. Calendar_LoadUI();
  449. if ( Calendar_Toggle ) then
  450. Calendar_Toggle();
  451. end
  452. end
  453. function ToggleGuildFrame()
  454. local factionGroup = UnitFactionGroup("player");
  455. if (IsBlizzCon() or factionGroup == "Neutral") then
  456. return;
  457. end
  458. if ( IsTrialAccount() ) then
  459. UIErrorsFrame:AddMessage(ERR_RESTRICTED_ACCOUNT, 1.0, 0.1, 0.1, 1.0);
  460. return;
  461. end
  462. if ( IsInGuild() ) then
  463. GuildFrame_LoadUI();
  464. if ( GuildFrame_Toggle ) then
  465. GuildFrame_Toggle();
  466. end
  467. else
  468. ToggleGuildFinder();
  469. end
  470. end
  471. function ToggleGuildFinder()
  472. local factionGroup = UnitFactionGroup("player");
  473. if (IsBlizzCon() or factionGroup == "Neutral") then
  474. return;
  475. end
  476. LookingForGuildFrame_LoadUI();
  477. if ( LookingForGuildFrame_Toggle ) then
  478. LookingForGuildFrame_Toggle();
  479. end
  480. end
  481. function ToggleLFDParentFrame()
  482. local factionGroup = UnitFactionGroup("player");
  483. if (IsBlizzCon() or factionGroup == "Neutral") then
  484. return;
  485. end
  486. if ( UnitLevel("player") >= SHOW_LFD_LEVEL ) then
  487. PVEFrame_ToggleFrame("GroupFinderFrame", LFDParentFrame);
  488. end
  489. end
  490. function ToggleHelpFrame()
  491. if ( HelpFrame:IsShown() ) then
  492. HideUIPanel(HelpFrame);
  493. else
  494. StaticPopup_Hide("HELP_TICKET");
  495. StaticPopup_Hide("HELP_TICKET_ABANDON_CONFIRM");
  496. StaticPopup_Hide("GM_RESPONSE_NEED_MORE_HELP");
  497. StaticPopup_Hide("GM_RESPONSE_RESOLVE_CONFIRM");
  498. StaticPopup_Hide("GM_RESPONSE_MUST_RESOLVE_RESPONSE");
  499. HelpFrame_ShowFrame();
  500. end
  501. end
  502. function ToggleRaidFrame()
  503. local factionGroup = UnitFactionGroup("player");
  504. if (IsBlizzCon() or factionGroup == "Neutral") then
  505. return;
  506. end
  507. ToggleFriendsFrame(4);
  508. end
  509. function ToggleRaidBrowser()
  510. local factionGroup = UnitFactionGroup("player");
  511. if (IsBlizzCon() or factionGroup == "Neutral") then
  512. return;
  513. end
  514. if ( RaidBrowserFrame:IsShown() ) then
  515. HideUIPanel(RaidBrowserFrame);
  516. else
  517. ShowUIPanel(RaidBrowserFrame);
  518. end
  519. end
  520. function ToggleEncounterJournal()
  521. if (IsBlizzCon()) then
  522. return;
  523. end
  524. if ( not EncounterJournal ) then
  525. EncounterJournal_LoadUI();
  526. end
  527. if ( EncounterJournal ) then
  528. ToggleFrame(EncounterJournal);
  529. end
  530. end
  531. function TogglePetJournal(whichFrame)
  532. if ( not PetJournalParent ) then
  533. PetJournal_LoadUI();
  534. end
  535. if ( PetJournalParent ) then
  536. ToggleFrame(PetJournalParent);
  537. end
  538. if (whichFrame and PetJournalParent:IsShown()) then
  539. PetJournalParent_SetTab(PetJournalParent, whichFrame);
  540. end
  541. end
  542. function TogglePVPUI()
  543. if (IsBlizzCon()) then
  544. return;
  545. end
  546. if (not PVPUIFrame) then
  547. PVP_LoadUI();
  548. end
  549. if ( UnitLevel("player") >= SHOW_PVP_LEVEL and not IsPlayerNeutral()) then
  550. PVPUIFrame_ToggleFrame()
  551. end
  552. end
  553. function InspectUnit(unit)
  554. if (IsBlizzCon()) then
  555. return;
  556. end
  557. InspectFrame_LoadUI();
  558. if ( InspectFrame_Show ) then
  559. InspectFrame_Show(unit);
  560. end
  561. end
  562. -- UIParent_OnEvent --
  563. function UIParent_OnEvent(self, event, ...)
  564. local arg1, arg2, arg3, arg4, arg5, arg6 = ...;
  565. if ( event == "CURRENT_SPELL_CAST_CHANGED" and #StaticPopup_DisplayedFrames > 0 ) then
  566. if ( arg1 ) then
  567. StaticPopup_Hide("BIND_ENCHANT");
  568. StaticPopup_Hide("REPLACE_ENCHANT");
  569. end
  570. StaticPopup_Hide("TRADE_REPLACE_ENCHANT");
  571. StaticPopup_Hide("END_BOUND_TRADEABLE");
  572. elseif ( event == "VARIABLES_LOADED" ) then
  573. LocalizeFrames();
  574. if ( WorldStateFrame_CanShowBattlefieldMinimap() ) then
  575. if ( not BattlefieldMinimap ) then
  576. BattlefieldMinimap_LoadUI();
  577. end
  578. BattlefieldMinimap:Show();
  579. end
  580. if ( not TimeManagerFrame and GetCVar("timeMgrAlarmEnabled") == "1" ) then
  581. -- We have to load the time manager here if the alarm is enabled because the alarm can go off
  582. -- even if the clock is not shown. WorldFrame_OnUpdate handles alarm checking while the clock
  583. -- is hidden.
  584. TimeManager_LoadUI();
  585. end
  586. local lastTalkedToGM = GetCVar("lastTalkedToGM");
  587. if ( lastTalkedToGM ~= "" ) then
  588. GMChatFrame_LoadUI();
  589. GMChatFrame:Show()
  590. local info = ChatTypeInfo["WHISPER"];
  591. GMChatFrame:AddMessage(format(GM_CHAT_LAST_SESSION, "|TInterface\\ChatFrame\\UI-ChatIcon-Blizz:12:20:0:0:32:16:4:28:0:16|t "..
  592. "|HplayerGM:"..lastTalkedToGM.."|h".."["..lastTalkedToGM.."]".."|h"), info.r, info.g, info.b, info.id);
  593. GMChatFrameEditBox:SetAttribute("tellTarget", lastTalkedToGM);
  594. GMChatFrameEditBox:SetAttribute("chatType", "WHISPER");
  595. end
  596. TargetFrame_OnVariablesLoaded();
  597. elseif ( event == "PLAYER_LOGIN" ) then
  598. TimeManager_LoadUI();
  599. -- You can override this if you want a Combat Log replacement
  600. CombatLog_LoadUI();
  601. elseif ( event == "PLAYER_DEAD" ) then
  602. if ( not StaticPopup_Visible("DEATH") ) then
  603. CloseAllWindows(1);
  604. end
  605. if ( GetReleaseTimeRemaining() > 0 or GetReleaseTimeRemaining() == -1 ) then
  606. StaticPopup_Show("DEATH");
  607. end
  608. elseif ( event == "SELF_RES_SPELL_CHANGED" ) then
  609. if ( StaticPopup_Visible("DEATH") ) then
  610. StaticPopup_Show("DEATH"); --If we're already showing a death prompt, we should refresh it.
  611. end
  612. elseif ( event == "PLAYER_ALIVE" or event == "RAISED_AS_GHOUL" ) then
  613. StaticPopup_Hide("DEATH");
  614. StaticPopup_Hide("RESURRECT_NO_SICKNESS");
  615. if ( UnitIsGhost("player") ) then
  616. GhostFrame:Show();
  617. else
  618. GhostFrame:Hide();
  619. end
  620. elseif ( event == "PLAYER_UNGHOST" ) then
  621. StaticPopup_Hide("RESURRECT");
  622. StaticPopup_Hide("RESURRECT_NO_SICKNESS");
  623. StaticPopup_Hide("RESURRECT_NO_TIMER");
  624. StaticPopup_Hide("SKINNED");
  625. StaticPopup_Hide("SKINNED_REPOP");
  626. GhostFrame:Hide();
  627. elseif ( event == "RESURRECT_REQUEST" ) then
  628. ShowResurrectRequest(arg1);
  629. elseif ( event == "PLAYER_SKINNED" ) then
  630. StaticPopup_Hide("RESURRECT");
  631. StaticPopup_Hide("RESURRECT_NO_SICKNESS");
  632. StaticPopup_Hide("RESURRECT_NO_TIMER");
  633. --[[
  634. if (arg1 == 1) then
  635. StaticPopup_Show("SKINNED_REPOP");
  636. else
  637. StaticPopup_Show("SKINNED");
  638. end
  639. ]]
  640. UIErrorsFrame:AddMessage(DEATH_CORPSE_SKINNED, 1.0, 0.1, 0.1, 1.0);
  641. elseif ( event == "TRADE_REQUEST" ) then
  642. StaticPopup_Show("TRADE", arg1);
  643. elseif ( event == "CHANNEL_INVITE_REQUEST" ) then
  644. local dialog = StaticPopup_Show("CHAT_CHANNEL_INVITE", arg1, arg2);
  645. if ( dialog ) then
  646. dialog.data = arg1;
  647. end
  648. elseif ( event == "CHANNEL_PASSWORD_REQUEST" ) then
  649. local dialog = StaticPopup_Show("CHAT_CHANNEL_PASSWORD", arg1);
  650. if ( dialog ) then
  651. dialog.data = arg1;
  652. end
  653. elseif ( event == "PARTY_INVITE_REQUEST" ) then
  654. -- if there's a role, it's an LFG invite
  655. if ( arg2 or arg3 or arg4 ) then
  656. StaticPopupSpecial_Show(LFGInvitePopup);
  657. LFGInvitePopup_Update(arg1, arg2, arg3, arg4);
  658. elseif ( arg5 ) then --It's a X-realm invite
  659. StaticPopup_Show("PARTY_INVITE_XREALM", arg1);
  660. else
  661. StaticPopup_Show("PARTY_INVITE", arg1);
  662. end
  663. elseif ( event == "PARTY_INVITE_CANCEL" ) then
  664. StaticPopup_Hide("PARTY_INVITE");
  665. StaticPopup_Hide("PARTY_INVITE_XREALM");
  666. StaticPopupSpecial_Hide(LFGInvitePopup);
  667. elseif ( event == "GUILD_INVITE_REQUEST" ) then
  668. StaticPopup_Show("GUILD_INVITE", arg1, arg2);
  669. elseif ( event == "GUILD_INVITE_CANCEL" ) then
  670. StaticPopup_Hide("GUILD_INVITE");
  671. elseif ( event == "ARENA_TEAM_INVITE_REQUEST" ) then
  672. StaticPopup_Show("ARENA_TEAM_INVITE", arg1, arg2);
  673. elseif ( event == "ARENA_TEAM_INVITE_CANCEL" ) then
  674. StaticPopup_Hide("ARENA_TEAM_INVITE");
  675. elseif ( event == "PLAYER_CAMPING" ) then
  676. StaticPopup_Show("CAMP");
  677. elseif ( event == "PLAYER_QUITING" ) then
  678. StaticPopup_Show("QUIT");
  679. elseif ( event == "LOGOUT_CANCEL" ) then
  680. StaticPopup_Hide("CAMP");
  681. StaticPopup_Hide("QUIT");
  682. elseif ( event == "LOOT_BIND_CONFIRM" ) then
  683. local texture, item, quantity, quality, locked = GetLootSlotInfo(arg1);
  684. local dialog = StaticPopup_Show("LOOT_BIND", ITEM_QUALITY_COLORS[quality].hex..item.."|r");
  685. if ( dialog ) then
  686. dialog.data = arg1;
  687. end
  688. elseif ( event == "EQUIP_BIND_CONFIRM" ) then
  689. StaticPopup_Hide("AUTOEQUIP_BIND");
  690. local dialog = StaticPopup_Show("EQUIP_BIND");
  691. if ( dialog ) then
  692. dialog.data = arg1;
  693. end
  694. elseif ( event == "AUTOEQUIP_BIND_CONFIRM" ) then
  695. StaticPopup_Hide("EQUIP_BIND");
  696. local dialog = StaticPopup_Show("AUTOEQUIP_BIND");
  697. if ( dialog ) then
  698. dialog.data = arg1;
  699. end
  700. elseif ( event == "USE_BIND_CONFIRM" ) then
  701. StaticPopup_Show("USE_BIND");
  702. elseif ( event == "CONFIRM_BEFORE_USE" ) then
  703. StaticPopup_Show("CONFIM_BEFORE_USE");
  704. elseif ( event == "DELETE_ITEM_CONFIRM" ) then
  705. -- Check quality
  706. if ( arg2 >= 3 ) then
  707. if (arg3 == 4) then -- quest item?
  708. StaticPopup_Show("DELETE_GOOD_QUEST_ITEM", arg1);
  709. else
  710. StaticPopup_Show("DELETE_GOOD_ITEM", arg1);
  711. end
  712. else
  713. if (arg3 == 4) then -- quest item?
  714. StaticPopup_Show("DELETE_QUEST_ITEM", arg1);
  715. else
  716. StaticPopup_Show("DELETE_ITEM", arg1);
  717. end
  718. end
  719. elseif ( event == "QUEST_ACCEPT_CONFIRM" ) then
  720. local numEntries, numQuests = GetNumQuestLogEntries();
  721. if( numQuests >= MAX_QUESTS) then
  722. StaticPopup_Show("QUEST_ACCEPT_LOG_FULL", arg1, arg2);
  723. else
  724. StaticPopup_Show("QUEST_ACCEPT", arg1, arg2);
  725. end
  726. elseif ( event =="QUEST_LOG_UPDATE" or event == "UNIT_QUEST_LOG_CHANGED" ) then
  727. local frameName = StaticPopup_Visible("QUEST_ACCEPT_LOG_FULL");
  728. if( frameName ) then
  729. local numEntries, numQuests = GetNumQuestLogEntries();
  730. local button = _G[frameName.."Button1"];
  731. if( numQuests < MAX_QUESTS ) then
  732. button:Enable();
  733. else
  734. button:Disable();
  735. end
  736. end
  737. elseif ( event == "CURSOR_UPDATE" ) then
  738. if ( not CursorHasItem() ) then
  739. StaticPopup_Hide("EQUIP_BIND");
  740. StaticPopup_Hide("AUTOEQUIP_BIND");
  741. end
  742. elseif ( event == "PLAYER_ENTERING_WORLD" ) then
  743. -- Get multi-actionbar states (before CloseAllWindows() since that may be hooked by AddOns)
  744. -- We don't want to call this, as the values GetActionBarToggles() returns are incorrect if it's called before the client mirrors SetActionBarToggles values from the server.
  745. -- SHOW_MULTI_ACTIONBAR_1, SHOW_MULTI_ACTIONBAR_2, SHOW_MULTI_ACTIONBAR_3, SHOW_MULTI_ACTIONBAR_4 = GetActionBarToggles();
  746. MultiActionBar_Update();
  747. -- Close any windows that were previously open
  748. CloseAllWindows(1);
  749. -- Until PVPFrame is checked in, this is placed here.
  750. for i=1, MAX_ARENA_TEAMS do
  751. GetArenaTeam(i);
  752. end
  753. VoiceChat_Toggle();
  754. UpdateMicroButtons();
  755. -- Fix for Bug 124392
  756. StaticPopup_Hide("LEVEL_GRANT_PROPOSED");
  757. StaticPopup_Hide("CONFIRM_LEAVE_BATTLEFIELD");
  758. local _, instanceType = IsInInstance();
  759. if ( instanceType == "arena" or instanceType == "pvp") then
  760. Arena_LoadUI();
  761. end
  762. if ( UnitIsGhost("player") ) then
  763. GhostFrame:Show();
  764. else
  765. GhostFrame:Hide();
  766. end
  767. if ( GetReleaseTimeRemaining() > 0 or GetReleaseTimeRemaining() == -1 ) then
  768. StaticPopup_Show("DEATH");
  769. end
  770. elseif ( event == "GROUP_ROSTER_UPDATE" ) then
  771. -- Hide/Show party member frames
  772. RaidOptionsFrame_UpdatePartyFrames();
  773. if ( not IsInGroup(LE_PARTY_CATEGORY_INSTANCE) ) then
  774. StaticPopup_Hide("CONFIRM_LEAVE_INSTANCE_PARTY");
  775. end
  776. elseif ( event == "MIRROR_TIMER_START" ) then
  777. MirrorTimer_Show(arg1, arg2, arg3, arg4, arg5, arg6);
  778. elseif ( event == "DUEL_REQUESTED" ) then
  779. StaticPopup_Show("DUEL_REQUESTED", arg1);
  780. elseif ( event == "DUEL_OUTOFBOUNDS" ) then
  781. StaticPopup_Show("DUEL_OUTOFBOUNDS");
  782. elseif ( event == "DUEL_INBOUNDS" ) then
  783. StaticPopup_Hide("DUEL_OUTOFBOUNDS");
  784. elseif ( event == "DUEL_FINISHED" ) then
  785. StaticPopup_Hide("DUEL_REQUESTED");
  786. StaticPopup_Hide("DUEL_OUTOFBOUNDS");
  787. elseif ( event == "PET_BATTLE_PVP_DUEL_REQUESTED" ) then
  788. StaticPopup_Show("PET_BATTLE_PVP_DUEL_REQUESTED", arg1);
  789. elseif ( event == "PET_BATTLE_PVP_DUEL_REQUEST_CANCEL" ) then
  790. StaticPopup_Hide("PET_BATTLE_PVP_DUEL_REQUESTED");
  791. elseif ( event == "PET_BATTLE_QUEUE_PROPOSE_MATCH" ) then
  792. PlaySound("UI_PetBattles_PVP_ThroughQueue");
  793. StaticPopupSpecial_Show(PetBattleQueueReadyFrame);
  794. elseif ( event == "PET_BATTLE_QUEUE_PROPOSAL_DECLINED" or event == "PET_BATTLE_QUEUE_PROPOSAL_ACCEPTED" ) then
  795. StaticPopupSpecial_Hide(PetBattleQueueReadyFrame);
  796. elseif ( event == "TRADE_REQUEST_CANCEL" ) then
  797. StaticPopup_Hide("TRADE");
  798. elseif ( event == "CONFIRM_XP_LOSS" ) then
  799. local resSicknessTime = GetResSicknessDuration();
  800. if ( resSicknessTime ) then
  801. local dialog = nil;
  802. if (UnitLevel("player") <= 10) then
  803. dialog = StaticPopup_Show("XP_LOSS_NO_DURABILITY", resSicknessTime);
  804. else
  805. dialog = StaticPopup_Show("XP_LOSS", resSicknessTime);
  806. end
  807. if ( dialog ) then
  808. dialog.data = resSicknessTime;
  809. end
  810. else
  811. local dialog = nil;
  812. if (UnitLevel("player") <= 10) then
  813. dialog = StaticPopup_Show("XP_LOSS_NO_SICKNESS_NO_DURABILITY");
  814. else
  815. dialog = StaticPopup_Show("XP_LOSS_NO_SICKNESS");
  816. end
  817. if ( dialog ) then
  818. dialog.data = 1;
  819. end
  820. end
  821. HideUIPanel(GossipFrame);
  822. elseif ( event == "CORPSE_IN_RANGE" ) then
  823. StaticPopup_Show("RECOVER_CORPSE");
  824. elseif ( event == "CORPSE_IN_INSTANCE" ) then
  825. StaticPopup_Show("RECOVER_CORPSE_INSTANCE");
  826. elseif ( event == "CORPSE_OUT_OF_RANGE" ) then
  827. StaticPopup_Hide("RECOVER_CORPSE");
  828. StaticPopup_Hide("RECOVER_CORPSE_INSTANCE");
  829. StaticPopup_Hide("XP_LOSS");
  830. elseif ( event == "AREA_SPIRIT_HEALER_IN_RANGE" ) then
  831. AcceptAreaSpiritHeal();
  832. StaticPopup_Show("AREA_SPIRIT_HEAL");
  833. elseif ( event == "AREA_SPIRIT_HEALER_OUT_OF_RANGE" ) then
  834. StaticPopup_Hide("AREA_SPIRIT_HEAL");
  835. elseif ( event == "BIND_ENCHANT" ) then
  836. StaticPopup_Show("BIND_ENCHANT");
  837. elseif ( event == "REPLACE_ENCHANT" ) then
  838. StaticPopup_Show("REPLACE_ENCHANT", arg1, arg2);
  839. elseif ( event == "TRADE_REPLACE_ENCHANT" ) then
  840. StaticPopup_Show("TRADE_REPLACE_ENCHANT", arg1, arg2);
  841. elseif ( event == "END_BOUND_TRADEABLE" ) then
  842. local dialog = StaticPopup_Show("END_BOUND_TRADEABLE", nil, nil, arg1);
  843. elseif ( event == "MACRO_ACTION_BLOCKED" or event == "ADDON_ACTION_BLOCKED" ) then
  844. if ( not INTERFACE_ACTION_BLOCKED_SHOWN ) then
  845. local info = ChatTypeInfo["SYSTEM"];
  846. DEFAULT_CHAT_FRAME:AddMessage(INTERFACE_ACTION_BLOCKED, info.r, info.g, info.b, info.id);
  847. INTERFACE_ACTION_BLOCKED_SHOWN = true;
  848. end
  849. elseif ( event == "MACRO_ACTION_FORBIDDEN" ) then
  850. StaticPopup_Show("MACRO_ACTION_FORBIDDEN");
  851. elseif ( event == "ADDON_ACTION_FORBIDDEN" ) then
  852. local dialog = StaticPopup_Show("ADDON_ACTION_FORBIDDEN", arg1);
  853. if ( dialog ) then
  854. dialog.data = arg1;
  855. end
  856. elseif ( event == "PLAYER_CONTROL_LOST" ) then
  857. if ( UnitOnTaxi("player") ) then
  858. return;
  859. end
  860. CloseAllWindows_WithExceptions();
  861. --[[
  862. -- Disable all microbuttons except the main menu
  863. SetDesaturation(MicroButtonPortrait, 1);
  864. Designers previously wanted these disabled when feared, they seem to have changed their minds
  865. CharacterMicroButton:Disable();
  866. SpellbookMicroButton:Disable();
  867. TalentMicroButton:Disable();
  868. QuestLogMicroButton:Disable();
  869. GuildMicroButton:Disable();
  870. WorldMapMicroButton:Disable();
  871. ]]
  872. UIParent.isOutOfControl = 1;
  873. elseif ( event == "PLAYER_CONTROL_GAINED" ) then
  874. --[[
  875. -- Enable all microbuttons
  876. SetDesaturation(MicroButtonPortrait, nil);
  877. CharacterMicroButton:Enable();
  878. SpellbookMicroButton:Enable();
  879. TalentMicroButton:Enable();
  880. QuestLogMicroButton:Enable();
  881. GuildMicroButton:Enable();
  882. WorldMapMicroButton:Enable();
  883. ]]
  884. UIParent.isOutOfControl = nil;
  885. elseif ( event == "START_LOOT_ROLL" ) then
  886. GroupLootFrame_OpenNewFrame(arg1, arg2);
  887. elseif ( event == "CONFIRM_LOOT_ROLL" ) then
  888. local texture, name, count, quality, bindOnPickUp = GetLootRollItemInfo(arg1);
  889. local dialog = StaticPopup_Show("CONFIRM_LOOT_ROLL", ITEM_QUALITY_COLORS[quality].hex..name.."|r");
  890. if ( dialog ) then
  891. dialog.text:SetFormattedText(arg3, ITEM_QUALITY_COLORS[quality].hex..name.."|r");
  892. StaticPopup_Resize(dialog, "CONFIRM_LOOT_ROLL");
  893. dialog.data = arg1;
  894. dialog.data2 = arg2;
  895. end
  896. elseif ( event == "MISSING_OUT_ON_LOOT" ) then
  897. MissingLootFrame_Show();
  898. elseif ( event == "SPELL_CONFIRMATION_PROMPT" ) then
  899. local spellID, confirmType, text, duration, currencyID = ...;
  900. if ( confirmType == CONFIRMATION_PROMPT_BONUS_ROLL ) then
  901. BonusRollFrame_StartBonusRoll(spellID, text, duration, currencyID);
  902. else
  903. StaticPopup_Show("SPELL_CONFIRMATION_PROMPT", text, duration, spellID);
  904. end
  905. elseif ( event == "SPELL_CONFIRMATION_TIMEOUT" ) then
  906. local spellID, confirmType = ...;
  907. if ( confirmType == CONFIRMATION_PROMPT_BONUS_ROLL ) then
  908. BonusRollFrame_CloseBonusRoll();
  909. else
  910. StaticPopup_Hide("SPELL_CONFIRMATION_PROMPT", spellID);
  911. end
  912. elseif ( event == "CONFIRM_DISENCHANT_ROLL" ) then
  913. local texture, name, count, quality, bindOnPickUp = GetLootRollItemInfo(arg1);
  914. local dialog = StaticPopup_Show("CONFIRM_LOOT_ROLL", ITEM_QUALITY_COLORS[quality].hex..name.."|r");
  915. if ( dialog ) then
  916. dialog.text:SetFormattedText(LOOT_NO_DROP_DISENCHANT, ITEM_QUALITY_COLORS[quality].hex..name.."|r");
  917. StaticPopup_Resize(dialog, "CONFIRM_LOOT_ROLL");
  918. dialog.data = arg1;
  919. dialog.data2 = arg2;
  920. end
  921. elseif ( event == "INSTANCE_BOOT_START" ) then
  922. StaticPopup_Show("INSTANCE_BOOT");
  923. elseif ( event == "INSTANCE_BOOT_STOP" ) then
  924. StaticPopup_Hide("INSTANCE_BOOT");
  925. elseif ( event == "INSTANCE_LOCK_START" ) then
  926. StaticPopup_Show("INSTANCE_LOCK", nil, nil, true);
  927. elseif ( event == "INSTANCE_LOCK_STOP" ) then
  928. StaticPopup_Hide("INSTANCE_LOCK");
  929. elseif ( event == "INSTANCE_LOCK_WARNING" ) then
  930. StaticPopup_Show("INSTANCE_LOCK", nil, nil, false);
  931. elseif ( event == "CONFIRM_TALENT_WIPE" ) then
  932. HideUIPanel(GossipFrame);
  933. StaticPopupDialogs["CONFIRM_TALENT_WIPE"].text = _G["CONFIRM_TALENT_WIPE_"..arg2];
  934. local dialog = StaticPopup_Show("CONFIRM_TALENT_WIPE");
  935. if ( dialog ) then
  936. MoneyFrame_Update(dialog:GetName().."MoneyFrame", arg1);
  937. -- open the talent UI to the player's active talent group...just so the player knows
  938. -- exactly which talent spec he is wiping
  939. -- TalentFrame_LoadUI();
  940. -- if ( PlayerTalentFrame_Open ) then
  941. -- PlayerTalentFrame_Open(GetActiveSpecGroup());
  942. -- end
  943. end
  944. elseif ( event == "CONFIRM_BINDER" ) then
  945. StaticPopup_Show("CONFIRM_BINDER", arg1);
  946. elseif ( event == "CONFIRM_SUMMON" ) then
  947. StaticPopup_Show("CONFIRM_SUMMON");
  948. elseif ( event == "CANCEL_SUMMON" ) then
  949. StaticPopup_Hide("CONFIRM_SUMMON");
  950. elseif ( event == "BILLING_NAG_DIALOG" ) then
  951. StaticPopup_Show("BILLING_NAG", arg1);
  952. elseif ( event == "IGR_BILLING_NAG_DIALOG" ) then
  953. StaticPopup_Show("IGR_BILLING_NAG");
  954. elseif ( event == "GOSSIP_CONFIRM" ) then
  955. if ( arg3 > 0 ) then
  956. StaticPopupDialogs["GOSSIP_CONFIRM"].hasMoneyFrame = 1;
  957. else
  958. StaticPopupDialogs["GOSSIP_CONFIRM"].hasMoneyFrame = nil;
  959. end
  960. local dialog = StaticPopup_Show("GOSSIP_CONFIRM", arg2);
  961. if ( dialog ) then
  962. dialog.data = arg1;
  963. if ( arg3 > 0 ) then
  964. MoneyFrame_Update(dialog:GetName().."MoneyFrame", arg3);
  965. end
  966. end
  967. elseif ( event == "GOSSIP_ENTER_CODE" ) then
  968. local dialog = StaticPopup_Show("GOSSIP_ENTER_CODE");
  969. if ( dialog ) then
  970. dialog.data = arg1;
  971. end
  972. elseif ( event == "GOSSIP_CONFIRM_CANCEL" or event == "GOSSIP_CLOSED" ) then
  973. StaticPopup_Hide("GOSSIP_CONFIRM");
  974. StaticPopup_Hide("GOSSIP_ENTER_CODE");
  975. --Events for handling Auction UI
  976. elseif ( event == "AUCTION_HOUSE_SHOW" ) then
  977. AuctionFrame_LoadUI();
  978. if ( AuctionFrame_Show ) then
  979. AuctionFrame_Show();
  980. end
  981. elseif ( event == "AUCTION_HOUSE_CLOSED" ) then
  982. if ( AuctionFrame_Hide ) then
  983. AuctionFrame_Hide();
  984. end
  985. elseif ( event == "AUCTION_HOUSE_DISABLED" ) then
  986. StaticPopup_Show("AUCTION_HOUSE_DISABLED");
  987. -- Events for trainer UI handling
  988. elseif ( event == "TRAINER_SHOW" ) then
  989. ClassTrainerFrame_LoadUI();
  990. if ( ClassTrainerFrame_Show ) then
  991. ClassTrainerFrame_Show();
  992. end
  993. elseif ( event == "TRAINER_CLOSED" ) then
  994. if ( ClassTrainerFrame_Hide ) then
  995. ClassTrainerFrame_Hide();
  996. end
  997. -- Events for trade skill UI handling
  998. elseif ( event == "TRADE_SKILL_SHOW" ) then
  999. TradeSkillFrame_LoadUI();
  1000. if ( TradeSkillFrame_Show ) then
  1001. TradeSkillFrame_Show();
  1002. end
  1003. elseif ( event == "TRADE_SKILL_CLOSE" ) then
  1004. if ( TradeSkillFrame_Hide ) then
  1005. TradeSkillFrame_Hide();
  1006. end
  1007. -- Event for item socketing handling
  1008. elseif ( event == "SOCKET_INFO_UPDATE" ) then
  1009. ItemSocketingFrame_LoadUI();
  1010. ItemSocketingFrame_Update();
  1011. ShowUIPanel(ItemSocketingFrame);
  1012. -- Event for BarberShop handling
  1013. elseif ( event == "BARBER_SHOP_OPEN" ) then
  1014. BarberShopFrame_LoadUI();
  1015. if ( BarberShopFrame ) then
  1016. ShowUIPanel(BarberShopFrame);
  1017. end
  1018. elseif ( event == "BARBER_SHOP_CLOSE" ) then
  1019. if ( BarberShopFrame and BarberShopFrame:IsVisible() ) then
  1020. BarberShopFrame:Hide();
  1021. end
  1022. -- Event for guildbank handling
  1023. elseif ( event == "GUILDBANKFRAME_OPENED" ) then
  1024. GuildBankFrame_LoadUI();
  1025. if ( GuildBankFrame ) then
  1026. ShowUIPanel(GuildBankFrame);
  1027. if ( not GuildBankFrame:IsVisible() ) then
  1028. CloseGuildBankFrame();
  1029. end
  1030. end
  1031. elseif ( event == "GUILDBANKFRAME_CLOSED" ) then
  1032. if ( GuildBankFrame ) then
  1033. HideUIPanel(GuildBankFrame);
  1034. end
  1035. -- Event for barbershop handling
  1036. elseif ( event == "BARBER_SHOP_OPEN" ) then
  1037. BarberShopFrame_LoadUI();
  1038. if ( BarberShopFrame ) then
  1039. ShowUIPanel(BarberShopFrame);
  1040. end
  1041. elseif ( event == "BARBER_SHOP_CLOSE" ) then
  1042. BarberShopFrame_LoadUI();
  1043. if ( BarberShopFrame ) then
  1044. HideUIPanel(BarberShopFrame);
  1045. end
  1046. -- Events for achievement handling
  1047. elseif ( event == "ACHIEVEMENT_EARNED" ) then
  1048. -- if ( not AchievementFrame ) then
  1049. -- AchievementFrame_LoadUI();
  1050. -- AchievementAlertFrame_ShowAlert(...);
  1051. -- end
  1052. -- self:UnregisterEvent(event);
  1053. -- Display instance reset info
  1054. elseif ( event == "RAID_INSTANCE_WELCOME" ) then
  1055. local dungeonName = arg1;
  1056. local lockExpireTime = arg2;
  1057. local locked = arg3;
  1058. local extended = arg4;
  1059. local message;
  1060. if ( locked == 0 ) then
  1061. message = format(RAID_INSTANCE_WELCOME, dungeonName, SecondsToTime(lockExpireTime, nil, 1))
  1062. else
  1063. if ( lockExpireTime == 0 ) then
  1064. message = format(RAID_INSTANCE_WELCOME_EXTENDED, dungeonName);
  1065. else
  1066. if ( extended == 0 ) then
  1067. message = format(RAID_INSTANCE_WELCOME_LOCKED, dungeonName, SecondsToTime(lockExpireTime, nil, 1));
  1068. else
  1069. message = format(RAID_INSTANCE_WELCOME_LOCKED_EXTENDED, dungeonName, SecondsToTime(lockExpireTime, nil, 1));
  1070. end
  1071. end
  1072. end
  1073. local info = ChatTypeInfo["SYSTEM"];
  1074. DEFAULT_CHAT_FRAME:AddMessage(message, info.r, info.g, info.b, info.id);
  1075. -- Events for taxi benchmarking
  1076. elseif ( event == "ENABLE_TAXI_BENCHMARK" ) then
  1077. if ( not FramerateText:IsShown() ) then
  1078. ToggleFramerate(true);
  1079. end
  1080. local info = ChatTypeInfo["SYSTEM"];
  1081. DEFAULT_CHAT_FRAME:AddMessage(BENCHMARK_TAXI_MODE_ON, info.r, info.g, info.b, info.id);
  1082. elseif ( event == "DISABLE_TAXI_BENCHMARK" ) then
  1083. if ( FramerateText.benchmark ) then
  1084. ToggleFramerate();
  1085. end
  1086. local info = ChatTypeInfo["SYSTEM"];
  1087. DEFAULT_CHAT_FRAME:AddMessage(BENCHMARK_TAXI_MODE_OFF, info.r, info.g, info.b, info.id);
  1088. -- Push to talk
  1089. elseif ( event == "VOICE_PUSH_TO_TALK_START" and GetVoiceCurrentSessionID() ) then
  1090. if ( GetCVarBool("PushToTalkSound") ) then
  1091. PlaySound("VoiceChatOn");
  1092. end
  1093. -- Animate the player frame speaker even if not broadcasting
  1094. if ( GetCVar("VoiceChatMode") == "0" ) then
  1095. UIFrameFadeIn(PlayerSpeakerFrame, 0.2, PlayerSpeakerFrame:GetAlpha(), 1);
  1096. end
  1097. elseif ( event == "VOICE_PUSH_TO_TALK_STOP" ) then
  1098. if ( GetCVarBool("PushToTalkSound") and GetVoiceCurrentSessionID() ) then
  1099. PlaySound("VoiceChatOff");
  1100. end
  1101. -- Stop Animation
  1102. if ( GetCVar("VoiceChatMode") == "0" and PlayerSpeakerFrame:GetAlpha() > 0 ) then
  1103. UIFrameFadeOut(PlayerSpeakerFrame, 0.2, PlayerSpeakerFrame:GetAlpha(), 0);
  1104. end
  1105. elseif ( event == "LEVEL_GRANT_PROPOSED" ) then
  1106. StaticPopup_Show("LEVEL_GRANT_PROPOSED", arg1);
  1107. elseif ( event == "CHAT_MSG_WHISPER" and arg6 == "GM" ) then --GMChatUI
  1108. GMChatFrame_LoadUI(event, ...);
  1109. elseif ( event == "WOW_MOUSE_NOT_FOUND" ) then
  1110. StaticPopup_Show("WOW_MOUSE_NOT_FOUND");
  1111. elseif ( event == "TALENTS_INVOLUNTARILY_RESET" ) then
  1112. if ( arg1 ) then
  1113. StaticPopup_Show("TALENTS_INVOLUNTARILY_RESET_PET");
  1114. else
  1115. StaticPopup_Show("TALENTS_INVOLUNTARILY_RESET");
  1116. end
  1117. -- Events for Reforging UI handling
  1118. elseif ( event == "FORGE_MASTER_OPENED" ) then
  1119. Reforging_LoadUI();
  1120. if ( ReforgingFrame_Show ) then
  1121. ReforgingFrame_Show();
  1122. end
  1123. elseif ( event == "FORGE_MASTER_CLOSED" ) then
  1124. if ( ReforgingFrame_Hide ) then
  1125. ReforgingFrame_Hide();
  1126. end
  1127. -- Events for Archaeology
  1128. elseif ( event == "ARCHAEOLOGY_TOGGLE" ) then
  1129. ArchaeologyFrame_LoadUI();
  1130. if ( ArchaeologyFrame_Show and not ArchaeologyFrame:IsShown()) then
  1131. ArchaeologyFrame_Show();
  1132. elseif ( ArchaeologyFrame_Hide ) then
  1133. ArchaeologyFrame_Hide();
  1134. end
  1135. -- Events for Transmogrify UI handling
  1136. elseif ( event == "TRANSMOGRIFY_OPEN" ) then
  1137. ItemAlteration_LoadUI();
  1138. if ( TransmogrifyFrame_Show ) then
  1139. TransmogrifyFrame_Show();
  1140. end
  1141. elseif ( event == "TRANSMOGRIFY_CLOSE" ) then
  1142. if ( TransmogrifyFrame_Hide ) then
  1143. TransmogrifyFrame_Hide();
  1144. end
  1145. -- Events for Void Storage UI handling
  1146. elseif ( event == "VOID_STORAGE_OPEN" ) then
  1147. VoidStorage_LoadUI();
  1148. if ( VoidStorageFrame_Show ) then
  1149. VoidStorageFrame_Show();
  1150. end
  1151. elseif ( event == "VOID_STORAGE_CLOSE" ) then
  1152. if ( VoidStorageFrame_Hide ) then
  1153. VoidStorageFrame_Hide();
  1154. end
  1155. --Events for Trial caps
  1156. elseif ( event == "TRIAL_CAP_REACHED_MONEY" ) then
  1157. TrialAccountCapReached_Inform("money");
  1158. elseif ( event == "TRIAL_CAP_REACHED_LEVEL" ) then
  1159. TrialAccountCapReached_Inform("level");
  1160. elseif( event == "SOR_START_EXPERIENCE_INCOMPLETE" ) then
  1161. StaticPopup_Show("ERR_SOR_STARTING_EXPERIENCE_INCOMPLETE");
  1162. -- Events for Black Market UI handling
  1163. elseif ( event == "BLACK_MARKET_OPEN" ) then
  1164. BlackMarket_LoadUI();
  1165. if ( BlackMarketFrame_Show ) then
  1166. BlackMarketFrame_Show();
  1167. end
  1168. elseif ( event == "BLACK_MARKET_CLOSE" ) then
  1169. if ( BlackMarketFrame_Hide ) then
  1170. BlackMarketFrame_Hide();
  1171. end
  1172. -- Events for Item Upgrading
  1173. elseif ( event == "ITEM_UPGRADE_MASTER_OPENED" ) then
  1174. ItemUpgrade_LoadUI();
  1175. if ( ItemUpgradeFrame_Show ) then
  1176. ItemUpgradeFrame_Show();
  1177. end
  1178. elseif ( event == "ITEM_UPGRADE_MASTER_CLOSED" ) then
  1179. if ( ItemUpgradeFrame_Hide ) then
  1180. ItemUpgradeFrame_Hide();
  1181. end
  1182. -- Events for Pet Journal
  1183. elseif ( event == "PET_JOURNAL_NEW_BATTLE_SLOT" ) then
  1184. CompanionsMicroButtonAlert:Show();
  1185. MicroButtonPulse(CompanionsMicroButton);
  1186. -- Quest Choice trigger event
  1187. elseif (event == "QUEST_CHOICE_UPDATE") then
  1188. QuestChoice_LoadUI();
  1189. if ( QuestChoiceFrame_Show) then
  1190. QuestChoiceFrame_Show();
  1191. end
  1192. end
  1193. end
  1194. -- Frame Management --
  1195. -- UIPARENT_MANAGED_FRAME_POSITIONS stores all the frames that have positioning dependencies based on other frames.
  1196. -- UIPARENT_MANAGED_FRAME_POSITIONS["FRAME"] = {
  1197. --Note: this is out of date and there are several more options now.
  1198. -- none = This value is used if no dependent frames are shown
  1199. -- reputation = This is the offset used if the reputation watch bar is shown
  1200. -- anchorTo = This is the object that the stored frame is anchored to
  1201. -- point = This is the point on the frame used as the anchor
  1202. -- rpoint = This is the point on the "anchorTo" frame that the stored frame is anchored to
  1203. -- bottomEither = This offset is used if either bottom multibar is shown
  1204. -- bottomLeft
  1205. -- var = If this is set use _G[varName] = value instead of setpoint
  1206. -- };
  1207. -- some standard offsets
  1208. local actionBarOffset = 45;
  1209. local menuBarTop = 55;
  1210. local overrideActionBarTop = 40;
  1211. local petBattleTop = 60;
  1212. function UpdateMenuBarTop ()
  1213. --Determines the optimal magic number based on resolution and action bar status.
  1214. menuBarTop = 55;
  1215. local width, height = string.match((({GetScreenResolutions()})[GetCurrentResolution()] or ""), "(%d+).-(%d+)");
  1216. if ( tonumber(width) / tonumber(height ) > 4/3 ) then
  1217. --Widescreen resolution
  1218. menuBarTop = 75;
  1219. end
  1220. end
  1221. UIPARENT_MANAGED_FRAME_POSITIONS = {
  1222. --Items with baseY set to "true" are positioned based on the value of menuBarTop and their offset needs to be repeatedly evaluated as menuBarTop can change.
  1223. --"yOffset" gets added to the value of "baseY", which is used for values based on menuBarTop.
  1224. ["MultiBarBottomLeft"] = {baseY = 17, reputation = 1, maxLevel = 1, anchorTo = "ActionButton1", point = "BOTTOMLEFT", rpoint = "TOPLEFT"};
  1225. ["MultiBarRight"] = {baseY = 98, reputation = 1, anchorTo = "UIParent", point = "BOTTOMRIGHT", rpoint = "BOTTOMRIGHT"};
  1226. ["VoiceChatTalkers"] = {baseY = true, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, reputation = 1};
  1227. ["GroupLootContainer"] = {baseY = true, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, reputation = 1};
  1228. ["MissingLootFrame"] = {baseY = true, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, reputation = 1};
  1229. ["TutorialFrameAlertButton"] = {baseY = true, yOffset = -10, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, reputation = 1};
  1230. ["FramerateLabel"] = {baseY = true, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, reputation = 1, playerPowerBarAlt = 1, extraActionBarFrame = 1};
  1231. ["CastingBarFrame"] = {baseY = true, yOffset = 40, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, reputation = 1, tutorialAlert = 1, playerPowerBarAlt = 1, extraActionBarFrame = 1};
  1232. ["PlayerPowerBarAlt"] = {baseY = true, yOffset = 40, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, reputation = 1, tutorialAlert = 1, extraActionBarFrame = 1};
  1233. ["ExtraActionBarFrame"] = {baseY = true, yOffset = 40, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, reputation = 1, tutorialAlert = 1};
  1234. ["ChatFrame1"] = {baseY = true, yOffset = 40, bottomLeft = actionBarOffset-8, justBottomRightAndStance = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, reputation = 1, maxLevel = 1, point = "BOTTOMLEFT", rpoint = "BOTTOMLEFT", xOffset = 32};
  1235. ["ChatFrame2"] = {baseY = true, yOffset = 40, bottomRight = actionBarOffset-8, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, rightLeft = -2*actionBarOffset, rightRight = -actionBarOffset, reputation = 1, maxLevel = 1, point = "BOTTOMRIGHT", rpoint = "BOTTOMRIGHT", xOffset = -32};
  1236. ["StanceBarFrame"] = {baseY = 0, bottomLeft = actionBarOffset, reputation = 1, maxLevel = 1, anchorTo = "MainMenuBar", point = "BOTTOMLEFT", rpoint = "TOPLEFT", xOffset = 30};
  1237. ["PossessBarFrame"] = {baseY = 0, bottomLeft = actionBarOffset, reputation = 1, maxLevel = 1, anchorTo = "MainMenuBar", point = "BOTTOMLEFT", rpoint = "TOPLEFT", xOffset = 30};
  1238. ["MultiCastActionBarFrame"] = {baseY = 0, bottomLeft = actionBarOffset, reputation = 1, maxLevel = 1, anchorTo = "MainMenuBar", point = "BOTTOMLEFT", rpoint = "TOPLEFT", xOffset = 30};
  1239. ["AuctionProgressFrame"] = {baseY = true, yOffset = 18, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, reputation = 1, tutorialAlert = 1};
  1240. -- Vars
  1241. -- These indexes require global variables of the same name to be declared. For example, if I have an index ["FOO"] then I need to make sure the global variable
  1242. -- FOO exists before this table is constructed. The function UIParent_ManageFramePosition will use the "FOO" table index to change the value of the FOO global
  1243. -- variable so that other modules can use the most up-to-date value of FOO without having knowledge of the UIPARENT_MANAGED_FRAME_POSITIONS table.
  1244. ["CONTAINER_OFFSET_X"] = {baseX = 0, rightLeft = 2*actionBarOffset+3, rightRight = actionBarOffset+3, isVar = "xAxis"};
  1245. ["CONTAINER_OFFSET_Y"] = {baseY = true, yOffset = 10, bottomEither = actionBarOffset, reputation = 1, isVar = "yAxis"};
  1246. ["BATTLEFIELD_TAB_OFFSET_Y"] = {baseY = 210, bottomRight = actionBarOffset, reputation = 1, isVar = "yAxis"};
  1247. ["PETACTIONBAR_YPOS"] = {baseY = 97, bottomLeft = actionBarOffset, justBottomRightAndStance = actionBarOffset, reputation = 1, maxLevel = 1, isVar = "yAxis"};
  1248. ["MULTICASTACTIONBAR_YPOS"] = {baseY = 0, bottomLeft = actionBarOffset, reputation = 1, maxLevel = 1, isVar = "yAxis"};
  1249. };
  1250. -- If any Var entries in UIPARENT_MANAGED_FRAME_POSITIONS are used exclusively by addons, they should be declared here and not in one of the addon's files.
  1251. -- The reason why is that it is possible for UIParent_ManageFramePosition to be run before the addon loads.
  1252. BATTLEFIELD_TAB_OFFSET_Y = 0;
  1253. -- constant offsets
  1254. for _, data in pairs(UIPARENT_MANAGED_FRAME_POSITIONS) do
  1255. for flag, value in pairs(data) do
  1256. if ( flag == "reputation" ) then
  1257. data[flag] = value * 9;
  1258. elseif ( flag == "maxLevel" ) then
  1259. data[flag] = value * -5;
  1260. elseif ( flag == "pet" ) then
  1261. data[flag] = value * 35;
  1262. elseif ( flag == "tutorialAlert" ) then
  1263. data[flag] = value * 35;
  1264. end
  1265. end
  1266. end
  1267. function UIParent_ManageFramePosition(index, value, yOffsetFrames, xOffsetFrames, hasBottomLeft, hasBottomRight, hasPetBar)
  1268. local frame, xOffset, yOffset, anchorTo, point, rpoint;
  1269. frame = _G[index];
  1270. if ( not frame or (type(frame)=="table" and frame.ignoreFramePositionManager)) then
  1271. return;
  1272. end
  1273. -- Always start with base as the base offset or default to zero if no "none" specified
  1274. xOffset = 0;
  1275. if ( value["baseX"] ) then
  1276. xOffset = value["baseX"];
  1277. elseif ( value["xOffset"] ) then
  1278. xOffset = value["xOffset"];
  1279. end
  1280. yOffset = 0;
  1281. if ( tonumber(value["baseY"]) ) then
  1282. --tonumber(nil) and tonumber(boolean) evaluate as nil, tonumber(number) evaluates as a number, which evaluates as true.
  1283. --This allows us to use the true value in baseY for flagging a frame's positioning as dependent upon the value of menuBarTop.
  1284. yOffset = value["baseY"];
  1285. elseif ( value["baseY"] ) then
  1286. --value["baseY"] is true, use menuBarTop.
  1287. yOffset = menuBarTop;
  1288. end
  1289. if ( value["yOffset"] ) then
  1290. --This is so things based on menuBarTop can still have an offset. Otherwise you'd just use put the offset value in baseY.
  1291. yOffset = yOffset + value["yOffset"];
  1292. end
  1293. -- Iterate through frames that affect y offsets
  1294. local hasBottomEitherFlag;
  1295. for _, flag in pairs(yOffsetFrames) do
  1296. if ( value[flag] ) then
  1297. if ( flag == "bottomEither" ) then
  1298. hasBottomEitherFlag = 1;
  1299. end
  1300. yOffset = yOffset + value[flag];
  1301. end
  1302. end
  1303. -- don't offset for the pet bar and bottomEither if the player has
  1304. -- the bottom right bar shown and not the bottom left
  1305. if ( hasBottomEitherFlag and hasBottomRight and hasPetBar and not hasBottomLeft ) then
  1306. yOffset = yOffset - (value["pet"] or 0);
  1307. end
  1308. -- Iterate through frames that affect x offsets
  1309. for _, flag in pairs(xOffsetFrames) do
  1310. if ( value[flag] ) then
  1311. xOffset = xOffset + value[flag];
  1312. end
  1313. end
  1314. -- Set up anchoring info
  1315. anchorTo = value["anchorTo"];
  1316. point = value["point"];
  1317. rpoint = value["rpoint"];
  1318. if ( not anchorTo ) then
  1319. anchorTo = "UIParent";
  1320. end
  1321. if ( not point ) then
  1322. point = "BOTTOM";
  1323. end
  1324. if ( not rpoint ) then
  1325. rpoint = "BOTTOM";
  1326. end
  1327. -- Anchor frame
  1328. if ( value["isVar"] ) then
  1329. if ( value["isVar"] == "xAxis" ) then
  1330. _G[index] = xOffset;
  1331. else
  1332. _G[index] = yOffset;
  1333. end
  1334. else
  1335. if ( frame ~= ChatFrame2 and not(frame:IsObjectType("frame") and frame:IsUserPlaced()) ) then
  1336. frame:SetPoint(point, anchorTo, rpoint, xOffset, yOffset);
  1337. end
  1338. end
  1339. end
  1340. local function FramePositionDelegate_OnAttributeChanged(self, attribute)
  1341. if ( attribute == "panel-show" ) then
  1342. local force = self:GetAttribute("panel-force");
  1343. local frame = self:GetAttribute("panel-frame");
  1344. self:ShowUIPanel(frame, force);
  1345. elseif ( attribute == "panel-hide" ) then
  1346. local frame = self:GetAttribute("panel-frame");
  1347. local skipSetPoint = self:GetAttribute("panel-skipSetPoint");
  1348. self:HideUIPanel(frame, skipSetPoint);
  1349. elseif ( attribute == "panel-update" ) then
  1350. local frame = self:GetAttribute("panel-frame");
  1351. self:UpdateUIPanelPositions(frame);
  1352. elseif ( attribute == "uiparent-manage" ) then
  1353. self:UIParentManageFramePositions();
  1354. end
  1355. end
  1356. local FramePositionDelegate = CreateFrame("FRAME");
  1357. FramePositionDelegate:SetScript("OnAttributeChanged", FramePositionDelegate_OnAttributeChanged);
  1358. function FramePositionDelegate:ShowUIPanel(frame, force)
  1359. local frameArea, framePushable;
  1360. frameArea = GetUIPanelWindowInfo(frame, "area");
  1361. if ( not CanOpenPanels() and frameArea ~= "center" and frameArea ~= "full" ) then
  1362. self:ShowUIPanelFailed(frame);
  1363. return;
  1364. end
  1365. framePushable = GetUIPanelWindowInfo(frame, "pushable") or 0;
  1366. if ( UnitIsDead("player") and not GetUIPanelWindowInfo(frame, "whileDead") ) then
  1367. NotWhileDeadError();
  1368. return;
  1369. end
  1370. -- If we have a full-screen frame open, ignore other non-fullscreen open requests
  1371. if ( self:GetUIPanel("fullscreen") and (frameArea ~= "full") ) then
  1372. if ( force ) then
  1373. self:SetUIPanel("fullscreen", nil, 1);
  1374. else
  1375. self:ShowUIPanelFailed(frame);
  1376. return;
  1377. end
  1378. end
  1379. -- If we have a "center" frame open, only listen to other "center" open requests
  1380. local centerFrame = self:GetUIPanel("center");
  1381. local centerArea, centerPushable;
  1382. if ( centerFrame ) then
  1383. if ( GetUIPanelWindowInfo(centerFrame, "allowOtherPanels") ) then
  1384. HideUIPanel(centerFrame);
  1385. centerFrame = nil;
  1386. else
  1387. centerArea = GetUIPanelWindowInfo(centerFrame, "area");
  1388. if ( centerArea and (centerArea == "center") and (frameArea ~= "center") and (frameArea ~= "full") ) then
  1389. if ( force ) then
  1390. self:SetUIPanel("center", nil, 1);
  1391. else
  1392. self:ShowUIPanelFailed(frame);
  1393. return;
  1394. end
  1395. end
  1396. centerPushable = GetUIPanelWindowInfo(centerFrame, "pushable") or 0;
  1397. end
  1398. end
  1399. -- Full-screen frames just replace each other
  1400. if ( frameArea == "full" ) then
  1401. securecall("CloseAllWindows");
  1402. self:SetUIPanel("fullscreen", frame);
  1403. return;
  1404. end
  1405. -- Native "center" frames just replace each other, and they take priority over pushed frames
  1406. if ( frameArea == "center" ) then
  1407. securecall("CloseWindows");
  1408. if ( not GetUIPanelWindowInfo(frame, "allowOtherPanels") ) then
  1409. securecall("CloseAllBags");
  1410. end
  1411. self:SetUIPanel("center", frame, 1);
  1412. return;
  1413. end
  1414. -- Doublewide frames take up the left and center spots
  1415. if ( frameArea == "doublewide" ) then
  1416. local leftFrame = self:GetUIPanel("left");
  1417. if ( leftFrame ) then
  1418. local leftPushable = GetUIPanelWindowInfo(leftFrame, "pushable") or 0;
  1419. if ( leftPushable > 0 and CanShowRightUIPanel(leftFrame) ) then
  1420. -- Push left to right
  1421. self:MoveUIPanel("left", "right", 1);
  1422. elseif ( centerFrame and CanShowRightUIPanel(centerFrame) ) then
  1423. self:MoveUIPanel("center", "right", 1);
  1424. end
  1425. end
  1426. self:SetUIPanel("doublewide", frame);
  1427. return;
  1428. end
  1429. -- If not pushable, close any doublewide frames
  1430. local doublewideFrame = self:GetUIPanel("doublewide");
  1431. if ( doublewideFrame ) then
  1432. if ( framePushable == 0 ) then
  1433. -- Set as left (closes doublewide) and slide over the right frame
  1434. self:SetUIPanel("left", frame, 1);
  1435. self:MoveUIPanel("right", "center");
  1436. elseif ( CanShowRightUIPanel(frame) ) then
  1437. -- Set as right
  1438. self:SetUIPanel("right", frame);
  1439. else
  1440. self:SetUIPanel("left", frame);
  1441. end
  1442. return;
  1443. end
  1444. -- Try to put it on the left
  1445. local leftFrame = self:GetUIPanel("left");
  1446. if ( not leftFrame ) then
  1447. self:SetUIPanel("left", frame);
  1448. return;
  1449. end
  1450. local leftPushable = GetUIPanelWindowInfo(leftFrame, "pushable") or 0;
  1451. -- Two open already
  1452. local rightFrame = self:GetUIPanel("right");
  1453. if ( centerFrame and not rightFrame ) then
  1454. -- If not pushable and left isn't pushable
  1455. if ( leftPushable == 0 and framePushable == 0 ) then
  1456. -- Replace left
  1457. self:SetUIPanel("left", frame);
  1458. elseif ( ( framePushable > centerPushable or centerArea == "center" ) and CanShowRightUIPanel(frame) ) then
  1459. -- This one is highest priority, show as right
  1460. self:SetUIPanel("right", frame);
  1461. elseif ( framePushable < leftPushable ) then
  1462. if ( centerArea == "center" ) then
  1463. if ( CanShowRightUIPanel(leftFrame) ) then
  1464. -- Skip center
  1465. self:MoveUIPanel("left", "right", 1);
  1466. self:SetUIPanel("left", frame);
  1467. else
  1468. -- Replace left
  1469. self:SetUIPanel("left", frame);
  1470. end
  1471. else
  1472. if ( CanShowUIPanels(frame, leftFrame, centerFrame) ) then
  1473. -- Shift both
  1474. self:MoveUIPanel("center", "right", 1);
  1475. self:MoveUIPanel("left", "center", 1);
  1476. self:SetUIPanel("left", frame);
  1477. else
  1478. -- Replace left
  1479. self:SetUIPanel("left", frame);
  1480. end
  1481. end
  1482. elseif ( framePushable <= centerPushable and centerArea ~= "center" and CanShowUIPanels(leftFrame, frame, centerFrame) ) then
  1483. -- Push center
  1484. self:MoveUIPanel("center", "right", 1);
  1485. self:SetUIPanel("center", frame);
  1486. elseif ( framePushable <= centerPushable and centerArea ~= "center" ) then
  1487. -- Replace left
  1488. self:SetUIPanel("left", frame);
  1489. else
  1490. -- Replace center
  1491. self:SetUIPanel("center", frame);
  1492. end
  1493. return;
  1494. end
  1495. -- If there's only one open...
  1496. if ( not centerFrame ) then
  1497. -- If neither is pushable, replace
  1498. if ( (leftPushable == 0) and (framePushable == 0) ) then
  1499. self:SetUIPanel("left", frame);
  1500. return;
  1501. end
  1502. -- Highest priority goes to center
  1503. if ( leftPushable > framePushable ) then
  1504. self:MoveUIPanel("left", "center", 1);
  1505. self:SetUIPanel("left", frame);
  1506. else
  1507. self:SetUIPanel("center", frame);
  1508. end
  1509. return;
  1510. end
  1511. -- Three are shown
  1512. local rightPushable = GetUIPanelWindowInfo(rightFrame, "pushable") or 0;
  1513. if ( framePushable > rightPushable ) then
  1514. -- This one is highest priority, slide the other two over
  1515. if ( CanShowUIPanels(centerFrame, rightFrame, frame) ) then
  1516. self:MoveUIPanel("center", "left", 1);
  1517. self:MoveUIPanel("right", "center", 1);
  1518. self:SetUIPanel("right", frame);
  1519. else
  1520. self:MoveUIPanel("right", "left", 1);
  1521. self:SetUIPanel("center", frame);
  1522. end
  1523. elseif ( framePushable > centerPushable ) then
  1524. -- This one is middle priority, so move the center frame to the left
  1525. self:MoveUIPanel("center", "left", 1);
  1526. self:SetUIPanel("center", frame);
  1527. else
  1528. self:SetUIPanel("left", frame);
  1529. end
  1530. end
  1531. function FramePositionDelegate:ShowUIPanelFailed(frame)
  1532. local showFailedFunc = _G[GetUIPanelWindowInfo(frame, "showFailedFunc")];
  1533. if ( showFailedFunc ) then
  1534. showFailedFunc(frame);
  1535. end
  1536. end
  1537. function FramePositionDelegate:SetUIPanel(key, frame, skipSetPoint)
  1538. if ( key == "fullscreen" ) then
  1539. local oldFrame = self.fullscreen;
  1540. self.fullscreen = frame;
  1541. if ( oldFrame ) then
  1542. oldFrame:Hide();
  1543. end
  1544. if ( frame ) then
  1545. UIParent:Hide();
  1546. frame:Show();
  1547. else
  1548. UIParent:Show();
  1549. SetUIVisibility(true);
  1550. end
  1551. return;
  1552. elseif ( key == "doublewide" ) then
  1553. local oldLeft = self.left;
  1554. local oldCenter = self.center;
  1555. local oldDoubleWide = self.doublewide;
  1556. self.doublewide = frame;
  1557. self.left = nil;
  1558. self.center = nil;
  1559. if ( oldDoubleWide ) then
  1560. oldDoubleWide:Hide();
  1561. end
  1562. if ( oldLeft ) then
  1563. oldLeft:Hide();
  1564. end
  1565. if ( oldCenter ) then
  1566. oldCenter:Hide();
  1567. end
  1568. elseif ( key ~= "left" and key ~= "center" and key ~= "right" ) then
  1569. return;
  1570. else
  1571. local oldFrame = self[key];
  1572. self[key] = frame;
  1573. if ( oldFrame ) then
  1574. oldFrame:Hide();
  1575. else
  1576. if ( self.doublewide ) then
  1577. if ( key == "left" or key == "center" ) then
  1578. self.doublewide:Hide();
  1579. self.doublewide = nil;
  1580. end
  1581. end
  1582. end
  1583. end
  1584. if ( not skipSetPoint ) then
  1585. securecall("UpdateUIPanelPositions", frame);
  1586. end
  1587. if ( frame ) then
  1588. frame:Show();
  1589. -- Hide all child windows
  1590. securecall("CloseChildWindows");
  1591. end
  1592. end
  1593. function FramePositionDelegate:MoveUIPanel(current, new, skipSetPoint)
  1594. if ( current ~= "left" and current ~= "center" and current ~= "right" and new ~= "left" and new ~= "center" and new ~= "right" ) then
  1595. return;
  1596. end
  1597. self:SetUIPanel(new, nil, skipSetPoint);
  1598. if ( self[current] ) then
  1599. self[current]:Raise();
  1600. self[new] = self[current];
  1601. self[current] = nil;
  1602. if ( not skipSetPoint ) then
  1603. securecall("UpdateUIPanelPositions");
  1604. end
  1605. end
  1606. end
  1607. function FramePositionDelegate:HideUIPanel(frame, skipSetPoint)
  1608. -- If we're hiding the full-screen frame, just hide it
  1609. if ( frame == self:GetUIPanel("fullscreen") ) then
  1610. self:SetUIPanel("fullscreen", nil);
  1611. return;
  1612. end
  1613. -- If we're hiding the right frame, just hide it
  1614. if ( frame == self:GetUIPanel("right") ) then
  1615. self:SetUIPanel("right", nil, skipSetPoint);
  1616. return;
  1617. elseif ( frame == self:GetUIPanel("doublewide") ) then
  1618. -- Slide over any right frame (hides the doublewide)
  1619. self:MoveUIPanel("right", "left", skipSetPoint);
  1620. return;
  1621. end
  1622. -- If we're hiding the center frame, slide over any right frame
  1623. local centerFrame = self:GetUIPanel("center");
  1624. if ( frame == centerFrame ) then
  1625. self:MoveUIPanel("right", "center", skipSetPoint);
  1626. elseif ( frame == self:GetUIPanel("left") ) then
  1627. -- If we're hiding the left frame, move the other frames left, unless the center is a native center frame
  1628. if ( centerFrame ) then
  1629. local area = GetUIPanelWindowInfo(centerFrame, "area");
  1630. if ( area ) then
  1631. if ( area == "center" ) then
  1632. -- Slide left, skip the center
  1633. self:MoveUIPanel("right", "left", skipSetPoint);
  1634. return;
  1635. else
  1636. -- Slide everything left
  1637. self:MoveUIPanel("center", "left", 1);
  1638. self:MoveUIPanel("right", "center", skipSetPoint);
  1639. return;
  1640. end
  1641. end
  1642. end
  1643. self:SetUIPanel("left", nil, skipSetPoint);
  1644. else
  1645. frame:Hide();
  1646. end
  1647. end
  1648. function FramePositionDelegate:GetUIPanel(key)
  1649. if ( key ~= "left" and key ~= "center" and key ~= "right" and key ~= "doublewide" and key ~= "fullscreen" ) then
  1650. return nil;
  1651. end
  1652. return self[key];
  1653. end
  1654. function FramePositionDelegate:UpdateUIPanelPositions(currentFrame)
  1655. if ( self.updatingPanels ) then
  1656. return;
  1657. end
  1658. self.updatingPanels = true;
  1659. local topOffset = UIParent:GetAttribute("TOP_OFFSET");
  1660. local leftOffset = UIParent:GetAttribute("LEFT_OFFSET");
  1661. local centerOffset = UIParent:GetAttribute("CENTER_OFFSET");
  1662. local rightOffset = UIParent:GetAttribute("RIGHT_OFFSET");
  1663. local xSpacing = UIParent:GetAttribute("PANEl_SPACING_X");
  1664. local info;
  1665. local frame = self:GetUIPanel("left");
  1666. if ( frame ) then
  1667. local xOff = GetUIPanelWindowInfo(frame,"xoffset") or 0;
  1668. local yOff = GetUIPanelWindowInfo(frame,"yoffset") or 0;
  1669. local yPos = ClampUIPanelY(frame, yOff + topOffset);
  1670. frame:ClearAllPoints();
  1671. frame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", leftOffset + xOff, yPos);
  1672. centerOffset = leftOffset + GetUIPanelWidth(frame) + xOff;
  1673. UIParent:SetAttribute("CENTER_OFFSET", centerOffset);
  1674. frame:Raise();
  1675. else
  1676. frame = self:GetUIPanel("doublewide");
  1677. if ( frame ) then
  1678. local xOff = GetUIPanelWindowInfo(frame,"xoffset") or 0;
  1679. local yOff = GetUIPanelWindowInfo(frame,"yoffset") or 0;
  1680. local yPos = ClampUIPanelY(frame, yOff + topOffset);
  1681. frame:ClearAllPoints();
  1682. frame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", leftOffset + xOff, yPos);
  1683. rightOffset = leftOffset + GetUIPanelWidth(frame) + xOff;
  1684. UIParent:SetAttribute("RIGHT_OFFSET", rightOffset);
  1685. frame:Raise();
  1686. end
  1687. end
  1688. frame = self:GetUIPanel("center");
  1689. if ( frame ) then
  1690. if ( CanShowCenterUIPanel(frame) ) then
  1691. local area = GetUIPanelWindowInfo(frame, "area");
  1692. local xOff = GetUIPanelWindowInfo(frame,"xoffset") or 0;
  1693. local yOff = GetUIPanelWindowInfo(frame,"yoffset") or 0;
  1694. local yPos = ClampUIPanelY(frame, yOff + topOffset);
  1695. if ( area ~= "center" ) then
  1696. frame:ClearAllPoints();
  1697. xOff = xOff + xSpacing; -- add sperating space
  1698. frame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", centerOffset + xOff, yPos);
  1699. end
  1700. rightOffset = centerOffset + GetUIPanelWidth(frame) + xOff;
  1701. else
  1702. if ( frame == currentFrame ) then
  1703. frame = self:GetUIPanel("left") or self:GetUIPanel("doublewide");
  1704. if ( frame ) then
  1705. self:HideUIPanel(frame);
  1706. self.updatingPanels = nil;
  1707. self:UpdateUIPanelPositions(currentFrame);
  1708. return;
  1709. end
  1710. end
  1711. self:SetUIPanel("center", nil, 1);
  1712. rightOffset = centerOffset + UIParent:GetAttribute("DEFAULT_FRAME_WIDTH");
  1713. end
  1714. frame:Raise();
  1715. elseif ( not self:GetUIPanel("doublewide") ) then
  1716. if ( self:GetUIPanel("left") ) then
  1717. rightOffset = centerOffset + UIParent:GetAttribute("DEFAULT_FRAME_WIDTH");
  1718. else
  1719. rightOffset = leftOffset + UIParent:GetAttribute("DEFAULT_FRAME_WIDTH") * 2
  1720. end
  1721. end
  1722. UIParent:SetAttribute("RIGHT_OFFSET", rightOffset);
  1723. frame = self:GetUIPanel("right");
  1724. if ( frame ) then
  1725. if ( CanShowRightUIPanel(frame) ) then
  1726. local xOff = GetUIPanelWindowInfo(frame,"xoffset") or 0;
  1727. local yOff = GetUIPanelWindowInfo(frame,"yoffset") or 0;
  1728. local yPos = ClampUIPanelY(frame, yOff + topOffset);
  1729. xOff = xOff + xSpacing; -- add sperating space
  1730. frame:ClearAllPoints();
  1731. frame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", rightOffset + xOff, yPos);
  1732. else
  1733. if ( frame == currentFrame ) then
  1734. frame = GetUIPanel("center") or GetUIPanel("left") or GetUIPanel("doublewide");
  1735. if ( frame ) then
  1736. self:HideUIPanel(frame);
  1737. self.updatingPanels = nil;
  1738. self:UpdateUIPanelPositions(currentFrame);
  1739. return;
  1740. end
  1741. end
  1742. self:SetUIPanel("right", nil, 1);
  1743. end
  1744. frame:Raise();
  1745. end
  1746. self.updatingPanels = nil;
  1747. end
  1748. function FramePositionDelegate:UIParentManageFramePositions()
  1749. -- Update the variable with the happy magic number.
  1750. UpdateMenuBarTop();
  1751. -- Frames that affect offsets in y axis
  1752. local yOffsetFrames = {};
  1753. -- Frames that affect offsets in x axis
  1754. local xOffsetFrames = {};
  1755. -- Set up flags
  1756. local hasBottomLeft, hasBottomRight, hasPetBar;
  1757. if ( OverrideActionBar and OverrideActionBar:IsShown() ) then
  1758. tinsert(yOffsetFrames, "overrideActionBar");
  1759. elseif ( PetBattleFrame and PetBattleFrame:IsShown() ) then
  1760. tinsert(yOffsetFrames, "petBattleFrame");
  1761. else
  1762. if ( MultiBarBottomLeft:IsShown() or MultiBarBottomRight:IsShown() ) then
  1763. tinsert(yOffsetFrames, "bottomEither");
  1764. end
  1765. if ( MultiBarBottomRight:IsShown() ) then
  1766. tinsert(yOffsetFrames, "bottomRight");
  1767. hasBottomRight = 1;
  1768. end
  1769. if ( MultiBarBottomLeft:IsShown() ) then
  1770. tinsert(yOffsetFrames, "bottomLeft");
  1771. hasBottomLeft = 1;
  1772. end
  1773. if ( MultiBarLeft:IsShown() ) then
  1774. tinsert(xOffsetFrames, "rightLeft");
  1775. elseif ( MultiBarRight:IsShown() ) then
  1776. tinsert(xOffsetFrames, "rightRight");
  1777. end
  1778. if (PetActionBarFrame_IsAboveStance and PetActionBarFrame_IsAboveStance()) then
  1779. tinsert(yOffsetFrames, "justBottomRightAndStance");
  1780. end
  1781. if ( ( PetActionBarFrame and PetActionBarFrame:IsShown() ) or ( StanceBarFrame and StanceBarFrame:IsShown() ) or
  1782. ( MultiCastActionBarFrame and MultiCastActionBarFrame:IsShown() ) or ( PossessBarFrame and PossessBarFrame:IsShown() ) or
  1783. ( MainMenuBarVehicleLeaveButton and MainMenuBarVehicleLeaveButton:IsShown() ) ) then
  1784. tinsert(yOffsetFrames, "pet");
  1785. hasPetBar = 1;
  1786. end
  1787. if ( ReputationWatchBar:IsShown() and MainMenuExpBar:IsShown() ) then
  1788. tinsert(yOffsetFrames, "reputation");
  1789. end
  1790. if ( MainMenuBarMaxLevelBar:IsShown() ) then
  1791. tinsert(yOffsetFrames, "maxLevel");
  1792. end
  1793. if ( TutorialFrameAlertButton:IsShown() ) then
  1794. tinsert(yOffsetFrames, "tutorialAlert");
  1795. end
  1796. if ( PlayerPowerBarAlt:IsShown() ) then
  1797. tinsert(yOffsetFrames, "playerPowerBarAlt");
  1798. end
  1799. if (ExtraActionBarFrame and ExtraActionBarFrame:IsShown() ) then
  1800. tinsert(yOffsetFrames, "extraActionBarFrame");
  1801. end
  1802. end
  1803. if ( menuBarTop == 55 ) then
  1804. UIPARENT_MANAGED_FRAME_POSITIONS["TutorialFrameAlertButton"].yOffset = -10;
  1805. else
  1806. UIPARENT_MANAGED_FRAME_POSITIONS["TutorialFrameAlertButton"].yOffset = -30;
  1807. end
  1808. -- Iterate through frames and set anchors according to the flags set
  1809. for index, value in pairs(UIPARENT_MANAGED_FRAME_POSITIONS) do
  1810. if ( value.playerPowerBarAlt ) then
  1811. value.playerPowerBarAlt = PlayerPowerBarAlt:GetHeight() + 10;
  1812. end
  1813. if ( value.extraActionBarFrame and ExtraActionBarFrame ) then
  1814. value.extraActionBarFrame = ExtraActionBarFrame:GetHeight() + 10;
  1815. end
  1816. if ( value.bonusActionBar and BonusActionBarFrame ) then
  1817. value.bonusActionBar = BonusActionBarFrame:GetHeight() - MainMenuBar:GetHeight();
  1818. end
  1819. securecall("UIParent_ManageFramePosition", index, value, yOffsetFrames, xOffsetFrames, hasBottomLeft, hasBottomRight, hasPetBar);
  1820. end
  1821. -- Custom positioning not handled by the loop
  1822. -- Update Stance bar appearance
  1823. if ( MultiBarBottomLeft:IsShown() ) then
  1824. SlidingActionBarTexture0:Hide();
  1825. SlidingActionBarTexture1:Hide();
  1826. if ( StanceBarFrame ) then
  1827. StanceBarLeft:Hide();
  1828. StanceBarRight:Hide();
  1829. StanceBarMiddle:Hide();
  1830. for i=1, NUM_STANCE_SLOTS do
  1831. _G["StanceButton"..i]:GetNormalTexture():SetWidth(52);
  1832. _G["StanceButton"..i]:GetNormalTexture():SetHeight(52);
  1833. end
  1834. end
  1835. else
  1836. if (PetActionBarFrame_IsAboveStance and PetActionBarFrame_IsAboveStance()) then
  1837. SlidingActionBarTexture0:Hide();
  1838. SlidingActionBarTexture1:Hide();
  1839. else
  1840. SlidingActionBarTexture0:Show();
  1841. SlidingActionBarTexture1:Show();
  1842. end
  1843. if ( StanceBarFrame ) then
  1844. if ( GetNumShapeshiftForms() > 2 ) then
  1845. StanceBarMiddle:Show();
  1846. end
  1847. StanceBarLeft:Show();
  1848. StanceBarRight:Show();
  1849. for i=1, NUM_STANCE_SLOTS do
  1850. _G["StanceButton"..i]:GetNormalTexture():SetWidth(64);
  1851. _G["StanceButton"..i]:GetNormalTexture():SetHeight(64);
  1852. end
  1853. end
  1854. end
  1855. -- HACK: we have too many bars in this game now...
  1856. -- if the Stance bar is shown then hide the multi-cast bar
  1857. -- we'll have to figure out what we should do in this case if it ever really becomes a problem
  1858. -- HACK 2: if the possession bar is shown then hide the multi-cast bar
  1859. -- yeah, way too many bars...
  1860. if ( ( StanceBarFrame and StanceBarFrame:IsShown() ) or
  1861. ( PossessBarFrame and PossessBarFrame:IsShown() ) ) then
  1862. HideMultiCastActionBar();
  1863. elseif ( HasMultiCastActionBar and HasMultiCastActionBar() ) then
  1864. ShowMultiCastActionBar();
  1865. end
  1866. -- If petactionbar is already shown, set its point in addition to changing its y target
  1867. if ( PetActionBarFrame:IsShown() ) then
  1868. PetActionBar_UpdatePositionValues();
  1869. PetActionBarFrame:SetPoint("TOPLEFT", MainMenuBar, "BOTTOMLEFT", PETACTIONBAR_XPOS, PETACTIONBAR_YPOS);
  1870. end
  1871. -- Set battlefield minimap position
  1872. if ( BattlefieldMinimapTab and not BattlefieldMinimapTab:IsUserPlaced() ) then
  1873. BattlefieldMinimapTab:SetPoint("BOTTOMLEFT", "UIParent", "BOTTOMRIGHT", -225-CONTAINER_OFFSET_X, BATTLEFIELD_TAB_OFFSET_Y);
  1874. end
  1875. -- Setup y anchors
  1876. local anchorY = 0
  1877. local buffsAnchorY = min(0, MINIMAP_BOTTOM_EDGE_EXTENT - BuffFrame.bottomEdgeExtent);
  1878. -- Count right action bars
  1879. local rightActionBars = 0;
  1880. if ( IsNormalActionBarState() ) then
  1881. if ( SHOW_MULTI_ACTIONBAR_3 ) then
  1882. rightActionBars = 1;
  1883. if ( SHOW_MULTI_ACTIONBAR_4 ) then
  1884. rightActionBars = 2;
  1885. end
  1886. end
  1887. end
  1888. -- Capture bars - need to move below buffs/debuffs if at least 1 right action bar is showing
  1889. if ( NUM_EXTENDED_UI_FRAMES ) then
  1890. local captureBar;
  1891. local numCaptureBars = 0;
  1892. for i=1, NUM_EXTENDED_UI_FRAMES do
  1893. captureBar = _G["WorldStateCaptureBar"..i];
  1894. if ( captureBar and captureBar:IsShown() ) then
  1895. numCaptureBars = numCaptureBars + 1
  1896. if ( numCaptureBars == 1 and rightActionBars > 0 ) then
  1897. anchorY = min(anchorY, buffsAnchorY);
  1898. end
  1899. captureBar:SetPoint("TOPRIGHT", MinimapCluster, "BOTTOMRIGHT", -CONTAINER_OFFSET_X, anchorY);
  1900. anchorY = anchorY - captureBar:GetHeight() - 4;
  1901. end
  1902. end
  1903. end
  1904. --Setup Vehicle seat indicator offset - needs to move below buffs/debuffs if both right action bars are showing
  1905. if ( VehicleSeatIndicator and VehicleSeatIndicator:IsShown() ) then
  1906. if ( rightActionBars == 2 ) then
  1907. anchorY = min(anchorY, buffsAnchorY);
  1908. VehicleSeatIndicator:SetPoint("TOPRIGHT", MinimapCluster, "BOTTOMRIGHT", -100, anchorY);
  1909. elseif ( rightActionBars == 1 ) then
  1910. VehicleSeatIndicator:SetPoint("TOPRIGHT", MinimapCluster, "BOTTOMRIGHT", -62, anchorY);
  1911. else
  1912. VehicleSeatIndicator:SetPoint("TOPRIGHT", MinimapCluster, "BOTTOMRIGHT", 0, anchorY);
  1913. end
  1914. anchorY = anchorY - VehicleSeatIndicator:GetHeight() - 4; --The -4 is there to give a small buffer for things like the QuestTimeFrame below the Seat Indicator
  1915. end
  1916. -- Boss frames - need to move below buffs/debuffs if both right action bars are showing
  1917. local numBossFrames = 0;
  1918. for i = 1, MAX_BOSS_FRAMES do
  1919. if ( _G["Boss"..i.."TargetFrame"]:IsShown() ) then
  1920. numBossFrames = i;
  1921. end
  1922. end
  1923. if ( numBossFrames > 0 ) then
  1924. if ( rightActionBars > 1 ) then
  1925. anchorY = min(anchorY, buffsAnchorY);
  1926. end
  1927. Boss1TargetFrame:SetPoint("TOPRIGHT", "MinimapCluster", "BOTTOMRIGHT", -(CONTAINER_OFFSET_X * 1.3) + 60, anchorY * 1.333); -- by 1.333 because it's 0.75 scale
  1928. anchorY = anchorY - (numBossFrames * (68 + BOSS_FRAME_CASTBAR_HEIGHT) + BOSS_FRAME_CASTBAR_HEIGHT);
  1929. end
  1930. -- Setup durability offset
  1931. if ( DurabilityFrame ) then
  1932. DurabilityFrame:SetPoint("TOPRIGHT", "MinimapCluster", "BOTTOMRIGHT", -CONTAINER_OFFSET_X, anchorY);
  1933. if ( DurabilityFrame:IsShown() ) then
  1934. anchorY = anchorY - DurabilityFrame:GetHeight();
  1935. end
  1936. end
  1937. if ( ArenaEnemyFrames ) then
  1938. ArenaEnemyFrames:ClearAllPoints();
  1939. ArenaEnemyFrames:SetPoint("TOPRIGHT", MinimapCluster, "BOTTOMRIGHT", -CONTAINER_OFFSET_X, anchorY);
  1940. end
  1941. if ( ArenaPrepFrames ) then
  1942. ArenaPrepFrames:ClearAllPoints();
  1943. ArenaPrepFrames:SetPoint("TOPRIGHT", MinimapCluster, "BOTTOMRIGHT", -CONTAINER_OFFSET_X, anchorY);
  1944. end
  1945. -- Watch frame - needs to move below buffs/debuffs if at least 1 right action bar is showing
  1946. if ( rightActionBars > 0 ) then
  1947. anchorY = min(anchorY, buffsAnchorY);
  1948. end
  1949. local numArenaOpponents = GetNumArenaOpponents();
  1950. if ( not WatchFrame:IsUserPlaced() ) then
  1951. if ( ArenaEnemyFrames and ArenaEnemyFrames:IsShown() and (numArenaOpponents > 0) ) then
  1952. WatchFrame:ClearAllPoints();
  1953. WatchFrame:SetPoint("TOPRIGHT", "ArenaEnemyFrame"..numArenaOpponents, "BOTTOMRIGHT", 2, -35);
  1954. elseif ( ArenaPrepFrames and ArenaPrepFrames:IsShown() and (numArenaOpponents > 0) ) then
  1955. WatchFrame:ClearAllPoints();
  1956. WatchFrame:SetPoint("TOPRIGHT", "ArenaPrepFrame"..numArenaOpponents, "BOTTOMRIGHT", 2, -35);
  1957. else
  1958. -- We're using Simple Quest Tracking, automagically size and position!
  1959. WatchFrame:ClearAllPoints();
  1960. -- move up if only the minimap cluster is above, move down a little otherwise
  1961. WatchFrame:SetPoint("TOPRIGHT", "MinimapCluster", "BOTTOMRIGHT", -CONTAINER_OFFSET_X, anchorY);
  1962. -- OnSizeChanged for WatchFrame handles its redraw
  1963. end
  1964. WatchFrame:SetPoint("BOTTOMRIGHT", "UIParent", "BOTTOMRIGHT", -CONTAINER_OFFSET_X, CONTAINER_OFFSET_Y);
  1965. end
  1966. -- Update chat dock since the dock could have moved
  1967. FCF_DockUpdate();
  1968. UpdateContainerFrameAnchors();
  1969. end
  1970. -- Call this function to update the positions of all frames that can appear on the right side of the screen
  1971. function UIParent_ManageFramePositions()
  1972. --Dispatch to secure code
  1973. FramePositionDelegate:SetAttribute("uiparent-manage", true);
  1974. end
  1975. function ToggleFrame(frame)
  1976. if ( frame:IsShown() ) then
  1977. HideUIPanel(frame);
  1978. else
  1979. ShowUIPanel(frame);
  1980. end
  1981. end
  1982. function ShowUIPanel(frame, force)
  1983. if ( not frame or frame:IsShown() ) then
  1984. return;
  1985. end
  1986. if ( not GetUIPanelWindowInfo(frame, "area") ) then
  1987. frame:Show();
  1988. return;
  1989. end
  1990. -- Dispatch to secure code
  1991. FramePositionDelegate:SetAttribute("panel-force", force);
  1992. FramePositionDelegate:SetAttribute("panel-frame", frame);
  1993. FramePositionDelegate:SetAttribute("panel-show", true);
  1994. end
  1995. function HideUIPanel(frame, skipSetPoint)
  1996. if ( not frame or not frame:IsShown() ) then
  1997. return;
  1998. end
  1999. if ( not GetUIPanelWindowInfo(frame, "area") ) then
  2000. frame:Hide();
  2001. return;
  2002. end
  2003. --Dispatch to secure code
  2004. FramePositionDelegate:SetAttribute("panel-frame", frame);
  2005. FramePositionDelegate:SetAttribute("panel-skipSetPoint", skipSetPoint);
  2006. FramePositionDelegate:SetAttribute("panel-hide", true);
  2007. end
  2008. function HideParentPanel(self)
  2009. HideUIPanel(self:GetParent());
  2010. end
  2011. function GetUIPanel(key)
  2012. return FramePositionDelegate:GetUIPanel(key);
  2013. end
  2014. function GetUIPanelWidth(frame)
  2015. return GetUIPanelWindowInfo(frame, "width") or frame:GetWidth() + (GetUIPanelWindowInfo(frame, "extraWidth") or 0);
  2016. end
  2017. function GetUIPanelHeight(frame)
  2018. return GetUIPanelWindowInfo(frame, "height") or frame:GetHeight() + (GetUIPanelWindowInfo(frame, "extraHeight") or 0);
  2019. end
  2020. --Allow a bit of overlap because there are built-in transparencies and buffers already
  2021. local MINIMAP_OVERLAP_ALLOWED = 60;
  2022. function GetMaxUIPanelsWidth()
  2023. --[[ local bufferBoundry = UIParent:GetRight() - UIParent:GetAttribute("RIGHT_OFFSET_BUFFER");
  2024. if ( Minimap:IsShown() and not MinimapCluster:IsUserPlaced() ) then
  2025. -- If the Minimap is in the default place, make sure you wont overlap it either
  2026. return min(MinimapCluster:GetLeft()+MINIMAP_OVERLAP_ALLOWED, bufferBoundry);
  2027. else
  2028. -- If the minimap has been moved, make sure not to overlap the right side bars
  2029. return bufferBoundry;
  2030. end
  2031. ]]
  2032. return UIParent:GetRight() - UIParent:GetAttribute("RIGHT_OFFSET_BUFFER");
  2033. end
  2034. function ClampUIPanelY(frame, yOffset)
  2035. local bottomPos = UIParent:GetTop() + yOffset - GetUIPanelHeight(frame);
  2036. if (bottomPos < 140) then
  2037. yOffset = yOffset + (140 - bottomPos);
  2038. end
  2039. if (yOffset > -10) then
  2040. yOffset = -10;
  2041. end
  2042. return yOffset;
  2043. end
  2044. function CanShowRightUIPanel(frame)
  2045. local width;
  2046. if ( frame ) then
  2047. width = GetUIPanelWidth(frame);
  2048. else
  2049. width = UIParent:GetAttribute("DEFAULT_FRAME_WIDTH");
  2050. end
  2051. local rightSide = UIParent:GetAttribute("RIGHT_OFFSET") + width;
  2052. if ( rightSide < GetMaxUIPanelsWidth() ) then
  2053. return 1;
  2054. end
  2055. end
  2056. function CanShowCenterUIPanel(frame)
  2057. local width;
  2058. if ( frame ) then
  2059. width = GetUIPanelWidth(frame);
  2060. else
  2061. width = UIParent:GetAttribute("DEFAULT_FRAME_WIDTH");
  2062. end
  2063. local rightSide = UIParent:GetAttribute("CENTER_OFFSET") + width;
  2064. if ( rightSide < GetMaxUIPanelsWidth() ) then
  2065. return 1;
  2066. end
  2067. end
  2068. function CanShowUIPanels(leftFrame, centerFrame, rightFrame)
  2069. local offset = UIParent:GetAttribute("LEFT_OFFSET");
  2070. if ( leftFrame ) then
  2071. offset = offset + GetUIPanelWidth(leftFrame);
  2072. if ( centerFrame ) then
  2073. local area = GetUIPanelWindowInfo(centerFrame, "area");
  2074. if ( area ~= "center" ) then
  2075. offset = offset + ( GetUIPanelWindowInfo(centerFrame, "width") or UIParent:GetAttribute("DEFAULT_FRAME_WIDTH") );
  2076. else
  2077. offset = offset + GetUIPanelWidth(centerFrame);
  2078. end
  2079. if ( rightFrame ) then
  2080. offset = offset + GetUIPanelWidth(rightFrame);
  2081. end
  2082. end
  2083. elseif ( centerFrame ) then
  2084. offset = GetUIPanelWidth(centerFrame);
  2085. end
  2086. if ( offset < GetMaxUIPanelsWidth() ) then
  2087. return 1;
  2088. end
  2089. end
  2090. function CanOpenPanels()
  2091. --[[
  2092. if ( UnitIsDead("player") ) then
  2093. return nil;
  2094. end
  2095. Previously couldn't open frames if player was out of control i.e. feared
  2096. if ( UnitIsDead("player") or UIParent.isOutOfControl ) then
  2097. return nil;
  2098. end
  2099. ]]
  2100. local centerFrame = GetUIPanel("center");
  2101. if ( not centerFrame ) then
  2102. return 1;
  2103. end
  2104. local area = GetUIPanelWindowInfo(centerFrame, "area");
  2105. local allowOtherPanels = GetUIPanelWindowInfo(centerFrame, "allowOtherPanels");
  2106. if ( area and (area == "center") and not allowOtherPanels ) then
  2107. return nil;
  2108. end
  2109. return 1;
  2110. end
  2111. -- this function handles possibly tainted values and so
  2112. -- should always be called from secure code using securecall()
  2113. function CloseChildWindows()
  2114. local childWindow;
  2115. for index, value in pairs(UIChildWindows) do
  2116. childWindow = _G[value];
  2117. if ( childWindow ) then
  2118. childWindow:Hide();
  2119. end
  2120. end
  2121. end
  2122. -- this function handles possibly tainted values and so
  2123. -- should always be called from secure code using securecall()
  2124. function CloseSpecialWindows()
  2125. local found;
  2126. for index, value in pairs(UISpecialFrames) do
  2127. local frame = _G[value];
  2128. if ( frame and frame:IsShown() ) then
  2129. frame:Hide();
  2130. found = 1;
  2131. end
  2132. end
  2133. return found;
  2134. end
  2135. function CloseWindows(ignoreCenter, frameToIgnore)
  2136. -- This function will close all frames that are not the current frame
  2137. local leftFrame = GetUIPanel("left");
  2138. local centerFrame = GetUIPanel("center");
  2139. local rightFrame = GetUIPanel("right");
  2140. local doublewideFrame = GetUIPanel("doublewide");
  2141. local fullScreenFrame = GetUIPanel("fullscreen");
  2142. local found = leftFrame or centerFrame or rightFrame or doublewideFrame or fullScreenFrame;
  2143. if ( not frameToIgnore or frameToIgnore ~= leftFrame ) then
  2144. HideUIPanel(leftFrame, 1);
  2145. end
  2146. HideUIPanel(fullScreenFrame, 1);
  2147. HideUIPanel(doublewideFrame, 1);
  2148. if ( not frameToIgnore or frameToIgnore ~= centerFrame ) then
  2149. if ( centerFrame ) then
  2150. local area = GetUIPanelWindowInfo(centerFrame, "area");
  2151. if ( area ~= "center" or not ignoreCenter ) then
  2152. HideUIPanel(centerFrame, 1);
  2153. end
  2154. end
  2155. end
  2156. if ( not frameToIgnore or frameToIgnore ~= rightFrame ) then
  2157. if ( rightFrame ) then
  2158. HideUIPanel(rightFrame, 1);
  2159. end
  2160. end
  2161. found = securecall("CloseSpecialWindows") or found;
  2162. UpdateUIPanelPositions();
  2163. return found;
  2164. end
  2165. function CloseAllWindows_WithExceptions()
  2166. -- Insert exceptions here, right now we just don't close the scoreFrame when the player loses control i.e. the game over spell effect
  2167. if ( GetUIPanel("center") == WorldStateScoreFrame ) then
  2168. CloseAllWindows(1);
  2169. elseif ( IsOptionFrameOpen() ) then
  2170. CloseAllWindows(1);
  2171. else
  2172. CloseAllWindows();
  2173. end
  2174. end
  2175. function CloseAllWindows(ignoreCenter)
  2176. local bagsVisible = nil;
  2177. local windowsVisible = nil;
  2178. for i=1, NUM_CONTAINER_FRAMES, 1 do
  2179. local containerFrame = _G["ContainerFrame"..i];
  2180. if ( containerFrame:IsShown() ) then
  2181. containerFrame:Hide();
  2182. bagsVisible = 1;
  2183. end
  2184. end
  2185. windowsVisible = CloseWindows(ignoreCenter);
  2186. return (bagsVisible or windowsVisible);
  2187. end
  2188. -- this function handles possibly tainted values and so
  2189. -- should always be called from secure code using securecall()
  2190. function CloseMenus()
  2191. local menusVisible = nil;
  2192. local menu
  2193. for index, value in pairs(UIMenus) do
  2194. menu = _G[value];
  2195. if ( menu and menu:IsShown() ) then
  2196. menu:Hide();
  2197. menusVisible = 1;
  2198. end
  2199. end
  2200. return menusVisible;
  2201. end
  2202. function UpdateUIPanelPositions(currentFrame)
  2203. FramePositionDelegate:SetAttribute("panel-frame", currentFrame)
  2204. FramePositionDelegate:SetAttribute("panel-update", true);
  2205. end
  2206. function IsOptionFrameOpen()
  2207. if ( GameMenuFrame:IsShown() or InterfaceOptionsFrame:IsShown() or (KeyBindingFrame and KeyBindingFrame:IsShown()) ) then
  2208. return 1;
  2209. else
  2210. return nil;
  2211. end
  2212. end
  2213. function LowerFrameLevel(frame)
  2214. frame:SetFrameLevel(frame:GetFrameLevel()-1);
  2215. end
  2216. function RaiseFrameLevel(frame)
  2217. frame:SetFrameLevel(frame:GetFrameLevel()+1);
  2218. end
  2219. function PassClickToParent(self, ...)
  2220. self:GetParent():Click(...);
  2221. end
  2222. -- Function to reposition frames if they get dragged off screen
  2223. function ValidateFramePosition(frame, offscreenPadding, returnOffscreen)
  2224. if ( not frame ) then
  2225. return;
  2226. end
  2227. local left = frame:GetLeft();
  2228. local right = frame:GetRight();
  2229. local top = frame:GetTop();
  2230. local bottom = frame:GetBottom();
  2231. local newAnchorX, newAnchorY;
  2232. if ( not offscreenPadding ) then
  2233. offscreenPadding = 15;
  2234. end
  2235. if ( bottom < (0 + MainMenuBar:GetHeight() + offscreenPadding)) then
  2236. -- Off the bottom of the screen
  2237. newAnchorY = MainMenuBar:GetHeight() + frame:GetHeight() - GetScreenHeight();
  2238. elseif ( top > GetScreenHeight() ) then
  2239. -- Off the top of the screen
  2240. newAnchorY = 0;
  2241. end
  2242. if ( left < 0 ) then
  2243. -- Off the left of the screen
  2244. newAnchorX = 0;
  2245. elseif ( right > GetScreenWidth() ) then
  2246. -- Off the right of the screen
  2247. newAnchorX = GetScreenWidth() - frame:GetWidth();
  2248. end
  2249. if ( newAnchorX or newAnchorY ) then
  2250. if ( returnOffscreen ) then
  2251. return 1;
  2252. else
  2253. if ( not newAnchorX ) then
  2254. newAnchorX = left;
  2255. elseif ( not newAnchorY ) then
  2256. newAnchorY = top - GetScreenHeight();
  2257. end
  2258. frame:ClearAllPoints();
  2259. frame:SetPoint("TOPLEFT", nil, "TOPLEFT", newAnchorX, newAnchorY);
  2260. end
  2261. else
  2262. if ( returnOffscreen ) then
  2263. return nil;
  2264. end
  2265. end
  2266. end
  2267. -- Time --
  2268. function SecondsToTime(seconds, noSeconds, notAbbreviated, maxCount, roundUp)
  2269. local time = "";
  2270. local count = 0;
  2271. local tempTime;
  2272. seconds = roundUp and ceil(seconds) or floor(seconds);
  2273. maxCount = maxCount or 2;
  2274. if ( seconds >= 86400 ) then
  2275. count = count + 1;
  2276. if ( count == maxCount and roundUp ) then
  2277. tempTime = ceil(seconds / 86400);
  2278. else
  2279. tempTime = floor(seconds / 86400);
  2280. end
  2281. if ( notAbbreviated ) then
  2282. time = format(D_DAYS,tempTime);
  2283. else
  2284. time = format(DAYS_ABBR,tempTime);
  2285. end
  2286. seconds = mod(seconds, 86400);
  2287. end
  2288. if ( count < maxCount and seconds >= 3600 ) then
  2289. count = count + 1;
  2290. if ( time ~= "" ) then
  2291. time = time..TIME_UNIT_DELIMITER;
  2292. end
  2293. if ( count == maxCount and roundUp ) then
  2294. tempTime = ceil(seconds / 3600);
  2295. else
  2296. tempTime = floor(seconds / 3600);
  2297. end
  2298. if ( notAbbreviated ) then
  2299. time = time..format(D_HOURS, tempTime);
  2300. else
  2301. time = time..format(HOURS_ABBR, tempTime);
  2302. end
  2303. seconds = mod(seconds, 3600);
  2304. end
  2305. if ( count < maxCount and seconds >= 60 ) then
  2306. count = count + 1;
  2307. if ( time ~= "" ) then
  2308. time = time..TIME_UNIT_DELIMITER;
  2309. end
  2310. if ( count == maxCount and roundUp ) then
  2311. tempTime = ceil(seconds / 60);
  2312. else
  2313. tempTime = floor(seconds / 60);
  2314. end
  2315. if ( notAbbreviated ) then
  2316. time = time..format(D_MINUTES, tempTime);
  2317. else
  2318. time = time..format(MINUTES_ABBR, tempTime);
  2319. end
  2320. seconds = mod(seconds, 60);
  2321. end
  2322. if ( count < maxCount and seconds > 0 and not noSeconds ) then
  2323. if ( time ~= "" ) then
  2324. time = time..TIME_UNIT_DELIMITER;
  2325. end
  2326. seconds = format("%d", seconds);
  2327. if ( notAbbreviated ) then
  2328. time = time..format(D_SECONDS, seconds);
  2329. else
  2330. time = time..format(SECONDS_ABBR, seconds);
  2331. end
  2332. end
  2333. return time;
  2334. end
  2335. function SecondsToTimeAbbrev(seconds)
  2336. local tempTime;
  2337. if ( seconds >= 86400 ) then
  2338. tempTime = ceil(seconds / 86400);
  2339. return DAY_ONELETTER_ABBR, tempTime;
  2340. end
  2341. if ( seconds >= 3600 ) then
  2342. tempTime = ceil(seconds / 3600);
  2343. return HOUR_ONELETTER_ABBR, tempTime;
  2344. end
  2345. if ( seconds >= 60 ) then
  2346. tempTime = ceil(seconds / 60);
  2347. return MINUTE_ONELETTER_ABBR, tempTime;
  2348. end
  2349. return SECOND_ONELETTER_ABBR, seconds;
  2350. end
  2351. function RecentTimeDate(year, month, day, hour)
  2352. local lastOnline;
  2353. if ( (year == 0) or (year == nil) ) then
  2354. if ( (month == 0) or (month == nil) ) then
  2355. if ( (day == 0) or (day == nil) ) then
  2356. if ( (hour == 0) or (hour == nil) ) then
  2357. lastOnline = LASTONLINE_MINS;
  2358. else
  2359. lastOnline = format(LASTONLINE_HOURS, hour);
  2360. end
  2361. else
  2362. lastOnline = format(LASTONLINE_DAYS, day);
  2363. end
  2364. else
  2365. lastOnline = format(LASTONLINE_MONTHS, month);
  2366. end
  2367. else
  2368. lastOnline = format(LASTONLINE_YEARS, year);
  2369. end
  2370. return lastOnline;
  2371. end
  2372. -- Frame fading and flashing --
  2373. local frameFadeManager = CreateFrame("FRAME");
  2374. -- Generic fade function
  2375. function UIFrameFade(frame, fadeInfo)
  2376. if (not frame) then
  2377. return;
  2378. end
  2379. if ( not fadeInfo.mode ) then
  2380. fadeInfo.mode = "IN";
  2381. end
  2382. local alpha;
  2383. if ( fadeInfo.mode == "IN" ) then
  2384. if ( not fadeInfo.startAlpha ) then
  2385. fadeInfo.startAlpha = 0;
  2386. end
  2387. if ( not fadeInfo.endAlpha ) then
  2388. fadeInfo.endAlpha = 1.0;
  2389. end
  2390. alpha = 0;
  2391. elseif ( fadeInfo.mode == "OUT" ) then
  2392. if ( not fadeInfo.startAlpha ) then
  2393. fadeInfo.startAlpha = 1.0;
  2394. end
  2395. if ( not fadeInfo.endAlpha ) then
  2396. fadeInfo.endAlpha = 0;
  2397. end
  2398. alpha = 1.0;
  2399. end
  2400. frame:SetAlpha(fadeInfo.startAlpha);
  2401. frame.fadeInfo = fadeInfo;
  2402. frame:Show();
  2403. local index = 1;
  2404. while FADEFRAMES[index] do
  2405. -- If frame is already set to fade then return
  2406. if ( FADEFRAMES[index] == frame ) then
  2407. return;
  2408. end
  2409. index = index + 1;
  2410. end
  2411. tinsert(FADEFRAMES, frame);
  2412. frameFadeManager:SetScript("OnUpdate", UIFrameFade_OnUpdate);
  2413. end
  2414. -- Convenience function to do a simple fade in
  2415. function UIFrameFadeIn(frame, timeToFade, startAlpha, endAlpha)
  2416. local fadeInfo = {};
  2417. fadeInfo.mode = "IN";
  2418. fadeInfo.timeToFade = timeToFade;
  2419. fadeInfo.startAlpha = startAlpha;
  2420. fadeInfo.endAlpha = endAlpha;
  2421. UIFrameFade(frame, fadeInfo);
  2422. end
  2423. -- Convenience function to do a simple fade out
  2424. function UIFrameFadeOut(frame, timeToFade, startAlpha, endAlpha)
  2425. local fadeInfo = {};
  2426. fadeInfo.mode = "OUT";
  2427. fadeInfo.timeToFade = timeToFade;
  2428. fadeInfo.startAlpha = startAlpha;
  2429. fadeInfo.endAlpha = endAlpha;
  2430. UIFrameFade(frame, fadeInfo);
  2431. end
  2432. function UIFrameFadeRemoveFrame(frame)
  2433. tDeleteItem(FADEFRAMES, frame);
  2434. end
  2435. -- Function that actually performs the alpha change
  2436. --[[
  2437. Fading frame attribute listing
  2438. ============================================================
  2439. frame.timeToFade [Num] Time it takes to fade the frame in or out
  2440. frame.mode ["IN", "OUT"] Fade mode
  2441. frame.finishedFunc [func()] Function that is called when fading is finished
  2442. frame.finishedArg1 [ANYTHING] Argument to the finishedFunc
  2443. frame.finishedArg2 [ANYTHING] Argument to the finishedFunc
  2444. frame.finishedArg3 [ANYTHING] Argument to the finishedFunc
  2445. frame.finishedArg4 [ANYTHING] Argument to the finishedFunc
  2446. frame.fadeHoldTime [Num] Time to hold the faded state
  2447. ]]
  2448. function UIFrameFade_OnUpdate(self, elapsed)
  2449. local index = 1;
  2450. local frame, fadeInfo;
  2451. while FADEFRAMES[index] do
  2452. frame = FADEFRAMES[index];
  2453. fadeInfo = FADEFRAMES[index].fadeInfo;
  2454. -- Reset the timer if there isn't one, this is just an internal counter
  2455. if ( not fadeInfo.fadeTimer ) then
  2456. fadeInfo.fadeTimer = 0;
  2457. end
  2458. fadeInfo.fadeTimer = fadeInfo.fadeTimer + elapsed;
  2459. -- If the fadeTimer is less then the desired fade time then set the alpha otherwise hold the fade state, call the finished function, or just finish the fade
  2460. if ( fadeInfo.fadeTimer < fadeInfo.timeToFade ) then
  2461. if ( fadeInfo.mode == "IN" ) then
  2462. frame:SetAlpha((fadeInfo.fadeTimer / fadeInfo.timeToFade) * (fadeInfo.endAlpha - fadeInfo.startAlpha) + fadeInfo.startAlpha);
  2463. elseif ( fadeInfo.mode == "OUT" ) then
  2464. frame:SetAlpha(((fadeInfo.timeToFade - fadeInfo.fadeTimer) / fadeInfo.timeToFade) * (fadeInfo.startAlpha - fadeInfo.endAlpha) + fadeInfo.endAlpha);
  2465. end
  2466. else
  2467. frame:SetAlpha(fadeInfo.endAlpha);
  2468. -- If there is a fadeHoldTime then wait until its passed to continue on
  2469. if ( fadeInfo.fadeHoldTime and fadeInfo.fadeHoldTime > 0 ) then
  2470. fadeInfo.fadeHoldTime = fadeInfo.fadeHoldTime - elapsed;
  2471. else
  2472. -- Complete the fade and call the finished function if there is one
  2473. UIFrameFadeRemoveFrame(frame);
  2474. if ( fadeInfo.finishedFunc ) then
  2475. fadeInfo.finishedFunc(fadeInfo.finishedArg1, fadeInfo.finishedArg2, fadeInfo.finishedArg3, fadeInfo.finishedArg4);
  2476. fadeInfo.finishedFunc = nil;
  2477. end
  2478. end
  2479. end
  2480. index = index + 1;
  2481. end
  2482. if ( #FADEFRAMES == 0 ) then
  2483. self:SetScript("OnUpdate", nil);
  2484. end
  2485. end
  2486. function UIFrameIsFading(frame)
  2487. for index, value in pairs(FADEFRAMES) do
  2488. if ( value == frame ) then
  2489. return 1;
  2490. end
  2491. end
  2492. return nil;
  2493. end
  2494. local frameFlashManager = CreateFrame("FRAME");
  2495. local UIFrameFlashTimers = {};
  2496. local UIFrameFlashTimerRefCount = {};
  2497. -- Function to start a frame flashing
  2498. function UIFrameFlash(frame, fadeInTime, fadeOutTime, flashDuration, showWhenDone, flashInHoldTime, flashOutHoldTime, syncId)
  2499. if ( frame ) then
  2500. local index = 1;
  2501. -- If frame is already set to flash then return
  2502. while FLASHFRAMES[index] do
  2503. if ( FLASHFRAMES[index] == frame ) then
  2504. return;
  2505. end
  2506. index = index + 1;
  2507. end
  2508. if (syncId) then
  2509. frame.syncId = syncId;
  2510. if (UIFrameFlashTimers[syncId] == nil) then
  2511. UIFrameFlashTimers[syncId] = 0;
  2512. UIFrameFlashTimerRefCount[syncId] = 0;
  2513. end
  2514. UIFrameFlashTimerRefCount[syncId] = UIFrameFlashTimerRefCount[syncId]+1;
  2515. else
  2516. frame.syncId = nil;
  2517. end
  2518. -- Time it takes to fade in a flashing frame
  2519. frame.fadeInTime = fadeInTime;
  2520. -- Time it takes to fade out a flashing frame
  2521. frame.fadeOutTime = fadeOutTime;
  2522. -- How long to keep the frame flashing
  2523. frame.flashDuration = flashDuration;
  2524. -- Show the flashing frame when the fadeOutTime has passed
  2525. frame.showWhenDone = showWhenDone;
  2526. -- Internal timer
  2527. frame.flashTimer = 0;
  2528. -- How long to hold the faded in state
  2529. frame.flashInHoldTime = flashInHoldTime;
  2530. -- How long to hold the faded out state
  2531. frame.flashOutHoldTime = flashOutHoldTime;
  2532. tinsert(FLASHFRAMES, frame);
  2533. frameFlashManager:SetScript("OnUpdate", UIFrameFlash_OnUpdate);
  2534. end
  2535. end
  2536. -- Called every frame to update flashing frames
  2537. function UIFrameFlash_OnUpdate(self, elapsed)
  2538. local frame;
  2539. local index = #FLASHFRAMES;
  2540. -- Update timers for all synced frames
  2541. for syncId, timer in pairs(UIFrameFlashTimers) do
  2542. UIFrameFlashTimers[syncId] = timer + elapsed;
  2543. end
  2544. while FLASHFRAMES[index] do
  2545. frame = FLASHFRAMES[index];
  2546. frame.flashTimer = frame.flashTimer + elapsed;
  2547. if ( (frame.flashTimer > frame.flashDuration) and frame.flashDuration ~= -1 ) then
  2548. UIFrameFlashStop(frame);
  2549. else
  2550. local flashTime = frame.flashTimer;
  2551. local alpha;
  2552. if (frame.syncId) then
  2553. flashTime = UIFrameFlashTimers[frame.syncId];
  2554. end
  2555. flashTime = flashTime%(frame.fadeInTime+frame.fadeOutTime+(frame.flashInHoldTime or 0)+(frame.flashOutHoldTime or 0));
  2556. if (flashTime < frame.fadeInTime) then
  2557. alpha = flashTime/frame.fadeInTime;
  2558. elseif (flashTime < frame.fadeInTime+(frame.flashInHoldTime or 0)) then
  2559. alpha = 1;
  2560. elseif (flashTime < frame.fadeInTime+(frame.flashInHoldTime or 0)+frame.fadeOutTime) then
  2561. alpha = 1 - ((flashTime - frame.fadeInTime - (frame.flashInHoldTime or 0))/frame.fadeOutTime);
  2562. else
  2563. alpha = 0;
  2564. end
  2565. frame:SetAlpha(alpha);
  2566. frame:Show();
  2567. end
  2568. -- Loop in reverse so that removing frames is safe
  2569. index = index - 1;
  2570. end
  2571. if ( #FLASHFRAMES == 0 ) then
  2572. self:SetScript("OnUpdate", nil);
  2573. end
  2574. end
  2575. -- Function to see if a frame is already flashing
  2576. function UIFrameIsFlashing(frame)
  2577. for index, value in pairs(FLASHFRAMES) do
  2578. if ( value == frame ) then
  2579. return 1;
  2580. end
  2581. end
  2582. return nil;
  2583. end
  2584. -- Function to stop flashing
  2585. function UIFrameFlashStop(frame)
  2586. tDeleteItem(FLASHFRAMES, frame);
  2587. frame:SetAlpha(1.0);
  2588. frame.flashTimer = nil;
  2589. if (frame.syncId) then
  2590. UIFrameFlashTimerRefCount[frame.syncId] = UIFrameFlashTimerRefCount[frame.syncId]-1;
  2591. if (UIFrameFlashTimerRefCount[frame.syncId] == 0) then
  2592. UIFrameFlashTimers[frame.syncId] = nil;
  2593. UIFrameFlashTimerRefCount[frame.syncId] = nil;
  2594. end
  2595. frame.syncId = nil;
  2596. end
  2597. if ( frame.showWhenDone ) then
  2598. frame:Show();
  2599. else
  2600. frame:Hide();
  2601. end
  2602. end
  2603. -- Functions to handle button pulsing (Highlight, Unhighlight)
  2604. function SetButtonPulse(button, duration, pulseRate)
  2605. button.pulseDuration = pulseRate;
  2606. button.pulseTimeLeft = duration
  2607. -- pulseRate is actually seconds per pulse state
  2608. button.pulseRate = pulseRate;
  2609. button.pulseOn = 0;
  2610. tinsert(PULSEBUTTONS, button);
  2611. end
  2612. -- Update the button pulsing
  2613. function ButtonPulse_OnUpdate(elapsed)
  2614. for index, button in pairs(PULSEBUTTONS) do
  2615. if ( button.pulseTimeLeft > 0 ) then
  2616. if ( button.pulseDuration < 0 ) then
  2617. if ( button.pulseOn == 1 ) then
  2618. button:UnlockHighlight();
  2619. button.pulseOn = 0;
  2620. else
  2621. button:LockHighlight();
  2622. button.pulseOn = 1;
  2623. end
  2624. button.pulseDuration = button.pulseRate;
  2625. end
  2626. button.pulseDuration = button.pulseDuration - elapsed;
  2627. button.pulseTimeLeft = button.pulseTimeLeft - elapsed;
  2628. else
  2629. button:UnlockHighlight();
  2630. button.pulseOn = 0;
  2631. tDeleteItem(PULSEBUTTONS, button);
  2632. end
  2633. end
  2634. end
  2635. function ButtonPulse_StopPulse(button)
  2636. for index, pulseButton in pairs(PULSEBUTTONS) do
  2637. if ( pulseButton == button ) then
  2638. tDeleteItem(PULSEBUTTONS, button);
  2639. end
  2640. end
  2641. end
  2642. function UIDoFramesIntersect(frame1, frame2)
  2643. if ( ( frame1:GetLeft() < frame2:GetRight() ) and ( frame1:GetRight() > frame2:GetLeft() ) and
  2644. ( frame1:GetBottom() < frame2:GetTop() ) and ( frame1:GetTop() > frame2:GetBottom() ) ) then
  2645. return true;
  2646. else
  2647. return false;
  2648. end
  2649. end
  2650. -- Lua Helper functions --
  2651. function BuildListString(...)
  2652. local text = ...;
  2653. if ( not text ) then
  2654. return nil;
  2655. end
  2656. local string = text;
  2657. for i=2, select("#", ...) do
  2658. text = select(i, ...);
  2659. if ( text ) then
  2660. string = string..", "..text;
  2661. end
  2662. end
  2663. return string;
  2664. end
  2665. function BuildColoredListString(...)
  2666. if ( select("#", ...) == 0 ) then
  2667. return nil;
  2668. end
  2669. -- Takes input where odd items are the text and even items determine whether the arg should be colored or not
  2670. local text, normal = ...;
  2671. local string;
  2672. if ( normal ) then
  2673. string = text;
  2674. else
  2675. string = RED_FONT_COLOR_CODE..text..FONT_COLOR_CODE_CLOSE;
  2676. end
  2677. for i=3, select("#", ...), 2 do
  2678. text, normal = select(i, ...);
  2679. if ( normal ) then
  2680. -- If meets the condition
  2681. string = string..", "..text;
  2682. else
  2683. -- If doesn't meet the condition
  2684. string = string..", "..RED_FONT_COLOR_CODE..text..FONT_COLOR_CODE_CLOSE;
  2685. end
  2686. end
  2687. return string;
  2688. end
  2689. function BuildNewLineListString(...)
  2690. local text;
  2691. local index = 1;
  2692. for i=1, select("#", ...) do
  2693. text = select(i, ...);
  2694. index = index + 1;
  2695. if ( text ) then
  2696. break;
  2697. end
  2698. end
  2699. if ( not text ) then
  2700. return nil;
  2701. end
  2702. local string = text;
  2703. for i=index, select("#", ...) do
  2704. text = select(i, ...);
  2705. if ( text ) then
  2706. string = string.."\n"..text;
  2707. end
  2708. end
  2709. return string;
  2710. end
  2711. function BuildMultilineTooltip(globalStringName, tooltip, r, g, b)
  2712. if ( not tooltip ) then
  2713. tooltip = GameTooltip;
  2714. end
  2715. if ( not r ) then
  2716. r = 1.0;
  2717. g = 1.0;
  2718. b = 1.0;
  2719. end
  2720. local i = 1;
  2721. local string = _G[globalStringName..i];
  2722. while (string) do
  2723. tooltip:AddLine(string, "", r, g, b);
  2724. i = i + 1;
  2725. string = _G[globalStringName..i];
  2726. end
  2727. end
  2728. function tDeleteItem(table, item)
  2729. local index = 1;
  2730. while table[index] do
  2731. if ( item == table[index] ) then
  2732. tremove(table, index);
  2733. else
  2734. index = index + 1;
  2735. end
  2736. end
  2737. end
  2738. function tContains(table, item)
  2739. local index = 1;
  2740. while table[index] do
  2741. if ( item == table[index] ) then
  2742. return 1;
  2743. end
  2744. index = index + 1;
  2745. end
  2746. return nil;
  2747. end
  2748. function CopyTable(settings)
  2749. local copy = {};
  2750. for k, v in pairs(settings) do
  2751. if ( type(v) == "table" ) then
  2752. copy[k] = CopyTable(v);
  2753. else
  2754. copy[k] = v;
  2755. end
  2756. end
  2757. return copy;
  2758. end
  2759. function MouseIsOver(region, topOffset, bottomOffset, leftOffset, rightOffset)
  2760. return region:IsMouseOver(topOffset, bottomOffset, leftOffset, rightOffset);
  2761. end
  2762. -- replace the C functions with local lua versions
  2763. function getglobal(varr)
  2764. return _G[varr];
  2765. end
  2766. function setglobal(varr,value)
  2767. _G[varr] = value;
  2768. end
  2769. -- Wrapper for the desaturation function
  2770. function SetDesaturation(texture, desaturation)
  2771. texture:SetDesaturated(desaturation);
  2772. end
  2773. function GetMaterialTextColors(material)
  2774. local textColor = MATERIAL_TEXT_COLOR_TABLE[material];
  2775. local titleColor = MATERIAL_TITLETEXT_COLOR_TABLE[material];
  2776. if ( not(textColor and titleColor) ) then
  2777. textColor = MATERIAL_TEXT_COLOR_TABLE["Default"];
  2778. titleColor = MATERIAL_TITLETEXT_COLOR_TABLE["Default"];
  2779. end
  2780. return textColor, titleColor;
  2781. end
  2782. -- Function that handles the escape key functions
  2783. function ToggleGameMenu()
  2784. if ( not UIParent:IsShown() ) then
  2785. UIParent:Show();
  2786. SetUIVisibility(true);
  2787. elseif ( securecall("StaticPopup_EscapePressed") ) then
  2788. elseif ( GameMenuFrame:IsShown() ) then
  2789. PlaySound("igMainMenuQuit");
  2790. HideUIPanel(GameMenuFrame);
  2791. elseif ( HelpFrame:IsShown() ) then
  2792. ToggleHelpFrame();
  2793. elseif ( VideoOptionsFrame:IsShown() ) then
  2794. VideoOptionsFrameCancel:Click();
  2795. elseif ( AudioOptionsFrame:IsShown() ) then
  2796. AudioOptionsFrameCancel:Click();
  2797. elseif ( InterfaceOptionsFrame:IsShown() ) then
  2798. InterfaceOptionsFrameCancel:Click();
  2799. elseif ( TimeManagerFrame and TimeManagerFrame:IsShown() ) then
  2800. TimeManagerFrameCloseButton:Click();
  2801. elseif ( MultiCastFlyoutFrame:IsShown() ) then
  2802. MultiCastFlyoutFrame_Hide(MultiCastFlyoutFrame, true);
  2803. elseif (SpellFlyout:IsShown() ) then
  2804. SpellFlyout:Hide();
  2805. elseif ( securecall("FCFDockOverflow_CloseLists") ) then
  2806. elseif ( securecall("CloseMenus") ) then
  2807. elseif ( CloseCalendarMenus and securecall("CloseCalendarMenus") ) then
  2808. elseif ( CloseGuildMenus and securecall("CloseGuildMenus") ) then
  2809. elseif ( SpellStopCasting() ) then
  2810. elseif ( SpellStopTargeting() ) then
  2811. elseif ( securecall("CloseAllWindows") ) then
  2812. elseif ( LootFrame:IsShown() ) then
  2813. -- if we're here, LootFrame was opened under the mouse (cvar "lootUnderMouse") so it didn't get closed by CloseAllWindows
  2814. LootFrame:Hide();
  2815. elseif ( ClearTarget() and (not UnitIsCharmed("player")) ) then
  2816. elseif ( OpacityFrame:IsShown() ) then
  2817. OpacityFrame:Hide();
  2818. else
  2819. PlaySound("igMainMenuOpen");
  2820. ShowUIPanel(GameMenuFrame);
  2821. end
  2822. end
  2823. -- Visual Misc --
  2824. function GetScreenHeightScale()
  2825. local screenHeight = 768;
  2826. return GetScreenHeight()/screenHeight;
  2827. end
  2828. function GetScreenWidthScale()
  2829. local screenWidth = 1024;
  2830. return GetScreenWidth()/screenWidth;
  2831. end
  2832. function ShowInspectCursor()
  2833. SetCursor("INSPECT_CURSOR");
  2834. end
  2835. -- Helper function to show the inspect cursor if the ctrl key is down
  2836. function CursorUpdate(self)
  2837. if ( IsModifiedClick("DRESSUP") and self.hasItem ) then
  2838. ShowInspectCursor();
  2839. else
  2840. ResetCursor();
  2841. end
  2842. end
  2843. function CursorOnUpdate(self)
  2844. if ( GameTooltip:IsOwned(self) ) then
  2845. CursorUpdate(self);
  2846. end
  2847. end
  2848. function AnimateTexCoords(texture, textureWidth, textureHeight, frameWidth, frameHeight, numFrames, elapsed, throttle)
  2849. if ( not texture.frame ) then
  2850. -- initialize everything
  2851. texture.frame = 1;
  2852. texture.throttle = throttle;
  2853. texture.numColumns = floor(textureWidth/frameWidth);
  2854. texture.numRows = floor(textureHeight/frameHeight);
  2855. texture.columnWidth = frameWidth/textureWidth;
  2856. texture.rowHeight = frameHeight/textureHeight;
  2857. end
  2858. local frame = texture.frame;
  2859. if ( not texture.throttle or texture.throttle > throttle ) then
  2860. local framesToAdvance = floor(texture.throttle / throttle);
  2861. while ( frame + framesToAdvance > numFrames ) do
  2862. frame = frame - numFrames;
  2863. end
  2864. frame = frame + framesToAdvance;
  2865. texture.throttle = 0;
  2866. local left = mod(frame-1, texture.numColumns)*texture.columnWidth;
  2867. local right = left + texture.columnWidth;
  2868. local bottom = ceil(frame/texture.numColumns)*texture.rowHeight;
  2869. local top = bottom - texture.rowHeight;
  2870. texture:SetTexCoord(left, right, top, bottom);
  2871. texture.frame = frame;
  2872. else
  2873. texture.throttle = texture.throttle + elapsed;
  2874. end
  2875. end
  2876. -- Bindings --
  2877. function GetBindingText(name, prefix, returnAbbr)
  2878. if ( not name ) then
  2879. return "";
  2880. end
  2881. local tempName = name;
  2882. local i = strfind(name, "-");
  2883. local dashIndex = nil;
  2884. local count = 0;
  2885. while ( i ) do
  2886. if ( not dashIndex ) then
  2887. dashIndex = i;
  2888. else
  2889. if ( i == 1 ) then
  2890. -- this means two "-" in a row, so it's "-" in combination with a modifier key
  2891. count = count - 1;
  2892. end
  2893. dashIndex = dashIndex + i;
  2894. end
  2895. count = count + 1;
  2896. tempName = strsub(tempName, i + 1);
  2897. i = strfind(tempName, "-");
  2898. end
  2899. local modKeys = '';
  2900. if ( not dashIndex ) then
  2901. dashIndex = 0;
  2902. else
  2903. modKeys = strsub(name, 1, dashIndex);
  2904. if ( tempName == "CAPSLOCK" ) then
  2905. gsub(tempName, "CAPSLOCK", "Caps");
  2906. end
  2907. -- replace for all languages
  2908. -- for the "push-to-talk" binding
  2909. modKeys = gsub(modKeys, "LSHIFT", LSHIFT_KEY_TEXT);
  2910. modKeys = gsub(modKeys, "RSHIFT", RSHIFT_KEY_TEXT);
  2911. modKeys = gsub(modKeys, "LCTRL", LCTRL_KEY_TEXT);
  2912. modKeys = gsub(modKeys, "RCTRL", RCTRL_KEY_TEXT);
  2913. modKeys = gsub(modKeys, "LALT", LALT_KEY_TEXT);
  2914. modKeys = gsub(modKeys, "RALT", RALT_KEY_TEXT);
  2915. -- use the SHIFT code if they decide to localize the CTRL further. The token is CTRL_KEY_TEXT
  2916. if ( GetLocale() == "deDE") then
  2917. modKeys = gsub(modKeys, "CTRL", "STRG");
  2918. end
  2919. -- Only doing French for now since all the other languages use SHIFT, remove the "if" if other languages localize it
  2920. if ( GetLocale() == "frFR" ) then
  2921. modKeys = gsub(modKeys, "SHIFT", SHIFT_KEY_TEXT);
  2922. end
  2923. end
  2924. if ( returnAbbr ) then
  2925. if ( count > 1 ) then
  2926. return "?";
  2927. else
  2928. modKeys = gsub(modKeys, "CTRL", "c");
  2929. modKeys = gsub(modKeys, "SHIFT", "s");
  2930. modKeys = gsub(modKeys, "ALT", "a");
  2931. modKeys = gsub(modKeys, "STRG", "st");
  2932. end
  2933. end
  2934. if ( not prefix ) then
  2935. prefix = "";
  2936. end
  2937. -- fix for bug 103620: mouse buttons are not being translated properly
  2938. if ( tempName == "LeftButton" ) then
  2939. tempName = "BUTTON1";
  2940. elseif ( tempName == "RightButton" ) then
  2941. tempName = "BUTTON2";
  2942. elseif ( tempName == "MiddleButton" ) then
  2943. tempName = "BUTTON3";
  2944. elseif ( tempName == "Button4" ) then
  2945. tempName = "BUTTON4";
  2946. elseif ( tempName == "Button5" ) then
  2947. tempName = "BUTTON5";
  2948. elseif ( tempName == "Button6" ) then
  2949. tempName = "BUTTON6";
  2950. elseif ( tempName == "Button7" ) then
  2951. tempName = "BUTTON7";
  2952. elseif ( tempName == "Button8" ) then
  2953. tempName = "BUTTON8";
  2954. elseif ( tempName == "Button9" ) then
  2955. tempName = "BUTTON9";
  2956. elseif ( tempName == "Button10" ) then
  2957. tempName = "BUTTON10";
  2958. elseif ( tempName == "Button11" ) then
  2959. tempName = "BUTTON11";
  2960. elseif ( tempName == "Button12" ) then
  2961. tempName = "BUTTON12";
  2962. elseif ( tempName == "Button13" ) then
  2963. tempName = "BUTTON13";
  2964. elseif ( tempName == "Button14" ) then
  2965. tempName = "BUTTON14";
  2966. elseif ( tempName == "Button15" ) then
  2967. tempName = "BUTTON15";
  2968. elseif ( tempName == "Button16" ) then
  2969. tempName = "BUTTON16";
  2970. elseif ( tempName == "Button17" ) then
  2971. tempName = "BUTTON17";
  2972. elseif ( tempName == "Button18" ) then
  2973. tempName = "BUTTON18";
  2974. elseif ( tempName == "Button19" ) then
  2975. tempName = "BUTTON19";
  2976. elseif ( tempName == "Button20" ) then
  2977. tempName = "BUTTON20";
  2978. elseif ( tempName == "Button21" ) then
  2979. tempName = "BUTTON21";
  2980. elseif ( tempName == "Button22" ) then
  2981. tempName = "BUTTON22";
  2982. elseif ( tempName == "Button23" ) then
  2983. tempName = "BUTTON23";
  2984. elseif ( tempName == "Button24" ) then
  2985. tempName = "BUTTON24";
  2986. elseif ( tempName == "Button25" ) then
  2987. tempName = "BUTTON25";
  2988. elseif ( tempName == "Button26" ) then
  2989. tempName = "BUTTON26";
  2990. elseif ( tempName == "Button27" ) then
  2991. tempName = "BUTTON27";
  2992. elseif ( tempName == "Button28" ) then
  2993. tempName = "BUTTON28";
  2994. elseif ( tempName == "Button29" ) then
  2995. tempName = "BUTTON29";
  2996. elseif ( tempName == "Button30" ) then
  2997. tempName = "BUTTON30";
  2998. elseif ( tempName == "Button31" ) then
  2999. tempName = "BUTTON31";
  3000. end
  3001. local localizedName = nil;
  3002. if ( IsMacClient() ) then
  3003. -- see if there is a mac specific name for the key
  3004. localizedName = _G[prefix..tempName.."_MAC"];
  3005. end
  3006. if ( not localizedName ) then
  3007. localizedName = _G[prefix..tempName];
  3008. end
  3009. -- for the "push-to-talk" binding it can be just a modifier key
  3010. if ( not localizedName ) then
  3011. localizedName = _G[tempName.."_KEY_TEXT"];
  3012. end
  3013. if ( not localizedName ) then
  3014. localizedName = tempName;
  3015. end
  3016. return modKeys..localizedName;
  3017. end
  3018. function GetBindingFromClick(input)
  3019. local fullInput = "";
  3020. -- MUST BE IN THIS ORDER (ALT, CTRL, SHIFT)
  3021. if ( IsAltKeyDown() ) then
  3022. fullInput = fullInput.."ALT-";
  3023. end
  3024. if ( IsControlKeyDown() ) then
  3025. fullInput = fullInput.."CTRL-"
  3026. end
  3027. if ( IsShiftKeyDown() ) then
  3028. fullInput = fullInput.."SHIFT-"
  3029. end
  3030. if ( input == "LeftButton" ) then
  3031. fullInput = fullInput.."BUTTON1";
  3032. elseif ( input == "RightButton" ) then
  3033. fullInput = fullInput.."BUTTON2";
  3034. elseif ( input == "MiddleButton" ) then
  3035. fullInput = fullInput.."BUTTON3";
  3036. elseif ( input == "Button4" ) then
  3037. fullInput = fullInput.."BUTTON4";
  3038. elseif ( input == "Button5" ) then
  3039. fullInput = fullInput.."BUTTON5";
  3040. elseif ( input == "Button6" ) then
  3041. fullInput = fullInput.."BUTTON6";
  3042. elseif ( input == "Button7" ) then
  3043. fullInput = fullInput.."BUTTON7";
  3044. elseif ( input == "Button8" ) then
  3045. fullInput = fullInput.."BUTTON8";
  3046. elseif ( input == "Button9" ) then
  3047. fullInput = fullInput.."BUTTON9";
  3048. elseif ( input == "Button10" ) then
  3049. fullInput = fullInput.."BUTTON10";
  3050. elseif ( input == "Button11" ) then
  3051. fullInput = fullInput.."BUTTON11";
  3052. elseif ( input == "Button12" ) then
  3053. fullInput = fullInput.."BUTTON12";
  3054. elseif ( input == "Button13" ) then
  3055. fullInput = fullInput.."BUTTON13";
  3056. elseif ( input == "Button14" ) then
  3057. fullInput = fullInput.."BUTTON14";
  3058. elseif ( input == "Button15" ) then
  3059. fullInput = fullInput.."BUTTON15";
  3060. elseif ( input == "Button16" ) then
  3061. fullInput = fullInput.."BUTTON16";
  3062. elseif ( input == "Button17" ) then
  3063. fullInput = fullInput.."BUTTON17";
  3064. elseif ( input == "Button18" ) then
  3065. fullInput = fullInput.."BUTTON18";
  3066. elseif ( input == "Button19" ) then
  3067. fullInput = fullInput.."BUTTON19";
  3068. elseif ( input == "Button20" ) then
  3069. fullInput = fullInput.."BUTTON20";
  3070. elseif ( input == "Button21" ) then
  3071. fullInput = fullInput.."BUTTON21";
  3072. elseif ( input == "Button22" ) then
  3073. fullInput = fullInput.."BUTTON22";
  3074. elseif ( input == "Button23" ) then
  3075. fullInput = fullInput.."BUTTON23";
  3076. elseif ( input == "Button24" ) then
  3077. fullInput = fullInput.."BUTTON24";
  3078. elseif ( input == "Button25" ) then
  3079. fullInput = fullInput.."BUTTON25";
  3080. elseif ( input == "Button26" ) then
  3081. fullInput = fullInput.."BUTTON26";
  3082. elseif ( input == "Button27" ) then
  3083. fullInput = fullInput.."BUTTON27";
  3084. elseif ( input == "Button28" ) then
  3085. fullInput = fullInput.."BUTTON28";
  3086. elseif ( input == "Button29" ) then
  3087. fullInput = fullInput.."BUTTON29";
  3088. elseif ( input == "Button30" ) then
  3089. fullInput = fullInput.."BUTTON30";
  3090. elseif ( input == "Button31" ) then
  3091. fullInput = fullInput.."BUTTON31";
  3092. else
  3093. fullInput = fullInput..input;
  3094. end
  3095. return GetBindingByKey(fullInput);
  3096. end
  3097. -- Game Logic --
  3098. function RealPartyIsFull()
  3099. if ( (GetNumSubgroupMembers(LE_PARTY_CATEGORY_HOME) < MAX_PARTY_MEMBERS) or (IsInRaid(LE_PARTY_CATEGORY_HOME) and (GetNumGroupMembers(LE_PARTY_CATEGORY_HOME) < MAX_RAID_MEMBERS)) ) then
  3100. return false;
  3101. else
  3102. return true;
  3103. end
  3104. end
  3105. function CanGroupInvite()
  3106. if ( IsInGroup() ) then
  3107. if ( UnitIsGroupLeader("player") or UnitIsGroupAssistant("player") ) then
  3108. return true;
  3109. else
  3110. return false;
  3111. end
  3112. else
  3113. return true;
  3114. end
  3115. end
  3116. function InviteToGroup(name)
  3117. if ( not IsInRaid() and GetNumGroupMembers() > MAX_PARTY_MEMBERS) then
  3118. local dialog = StaticPopup_Show("CONVERT_TO_RAID");
  3119. if ( dialog ) then
  3120. dialog.data = name;
  3121. end
  3122. else
  3123. InviteUnit(name);
  3124. end
  3125. end
  3126. function UnitHasMana(unit)
  3127. if ( UnitPowerMax(unit, SPELL_POWER_MANA) > 0 ) then
  3128. return 1;
  3129. end
  3130. return nil;
  3131. end
  3132. function RaiseFrameLevelByTwo(frame)
  3133. -- We do this enough that it saves closures.
  3134. frame:SetFrameLevel(frame:GetFrameLevel()+2);
  3135. end
  3136. function ShowResurrectRequest(offerer)
  3137. if ( ResurrectHasSickness() ) then
  3138. StaticPopup_Show("RESURRECT", offerer);
  3139. elseif ( ResurrectHasTimer() ) then
  3140. StaticPopup_Show("RESURRECT_NO_SICKNESS", offerer);
  3141. else
  3142. StaticPopup_Show("RESURRECT_NO_TIMER", offerer);
  3143. end
  3144. end
  3145. function RefreshAuras(frame, unit, numAuras, suffix, checkCVar, showBuffs)
  3146. if ( showBuffs ) then
  3147. RefreshBuffs(frame, unit, numAuras, suffix, checkCVar);
  3148. else
  3149. RefreshDebuffs(frame, unit, numAuras, suffix, checkCVar);
  3150. end
  3151. end
  3152. function RefreshBuffs(frame, unit, numBuffs, suffix, checkCVar)
  3153. local frameName = frame:GetName();
  3154. frame.hasDispellable = nil;
  3155. numBuffs = numBuffs or MAX_PARTY_BUFFS;
  3156. suffix = suffix or "Buff";
  3157. local unitStatus, statusColor;
  3158. local debuffTotal = 0;
  3159. local name, rank, icon, count, debuffType, duration, expirationTime;
  3160. local filter;
  3161. if ( checkCVar and SHOW_CASTABLE_BUFFS == "1" and UnitCanAssist("player", unit) ) then
  3162. filter = "RAID";
  3163. end
  3164. for i=1, numBuffs do
  3165. name, rank, icon, count, debuffType, duration, expirationTime = UnitBuff(unit, i, filter);
  3166. local buffName = frameName..suffix..i;
  3167. if ( icon ) then
  3168. -- if we have an icon to show then proceed with setting up the aura
  3169. -- set the icon
  3170. local buffIcon = _G[buffName.."Icon"];
  3171. buffIcon:SetTexture(icon);
  3172. -- setup the cooldown
  3173. local coolDown = _G[buffName.."Cooldown"];
  3174. if ( coolDown ) then
  3175. CooldownFrame_SetTimer(coolDown, expirationTime - duration, duration, 1);
  3176. end
  3177. -- show the aura
  3178. _G[buffName]:Show();
  3179. else
  3180. -- no icon, hide the aura
  3181. _G[buffName]:Hide();
  3182. end
  3183. end
  3184. end
  3185. function RefreshDebuffs(frame, unit, numDebuffs, suffix, checkCVar)
  3186. local frameName = frame:GetName();
  3187. frame.hasDispellable = nil;
  3188. numDebuffs = numDebuffs or MAX_PARTY_DEBUFFS;
  3189. suffix = suffix or "Debuff";
  3190. local unitStatus, statusColor;
  3191. local debuffTotal = 0;
  3192. local name, rank, icon, count, debuffType, duration, expirationTime, caster;
  3193. local isEnemy = UnitCanAttack("player", unit);
  3194. local filter;
  3195. if ( checkCVar and SHOW_DISPELLABLE_DEBUFFS == "1" and UnitCanAssist("player", unit) ) then
  3196. filter = "RAID";
  3197. end
  3198. for i=1, numDebuffs do
  3199. if ( unit == "party"..i ) then
  3200. unitStatus = _G[frameName.."Status"];
  3201. end
  3202. name, rank, icon, count, debuffType, duration, expirationTime, caster = UnitDebuff(unit, i, filter);
  3203. local debuffName = frameName..suffix..i;
  3204. if ( icon and ( SHOW_CASTABLE_DEBUFFS == "0" or not isEnemy or caster == "player" ) ) then
  3205. -- if we have an icon to show then proceed with setting up the aura
  3206. -- set the icon
  3207. local debuffIcon = _G[debuffName.."Icon"];
  3208. debuffIcon:SetTexture(icon);
  3209. -- setup the border
  3210. local debuffBorder = _G[debuffName.."Border"];
  3211. local debuffColor = DebuffTypeColor[debuffType] or DebuffTypeColor["none"];
  3212. debuffBorder:SetVertexColor(debuffColor.r, debuffColor.g, debuffColor.b);
  3213. -- record interesting data for the aura button
  3214. statusColor = debuffColor;
  3215. frame.hasDispellable = 1;
  3216. debuffTotal = debuffTotal + 1;
  3217. -- setup the cooldown
  3218. local coolDown = _G[debuffName.."Cooldown"];
  3219. if ( coolDown ) then
  3220. CooldownFrame_SetTimer(coolDown, expirationTime - duration, duration, 1);
  3221. end
  3222. -- show the aura
  3223. _G[debuffName]:Show();
  3224. else
  3225. -- no icon, hide the aura
  3226. _G[debuffName]:Hide();
  3227. end
  3228. end
  3229. frame.debuffTotal = debuffTotal;
  3230. -- Reset unitStatus overlay graphic timer
  3231. if ( frame.numDebuffs and debuffTotal >= frame.numDebuffs ) then
  3232. frame.debuffCountdown = 30;
  3233. end
  3234. if ( unitStatus and statusColor ) then
  3235. unitStatus:SetVertexColor(statusColor.r, statusColor.g, statusColor.b);
  3236. end
  3237. end
  3238. function GetQuestDifficultyColor(level)
  3239. return GetRelativeDifficultyColor(UnitLevel("player"), level);
  3240. end
  3241. --How difficult is this challenge for this unit?
  3242. function GetRelativeDifficultyColor(unitLevel, challengeLevel)
  3243. local levelDiff = challengeLevel - unitLevel;
  3244. local color;
  3245. if ( levelDiff >= 5 ) then
  3246. return QuestDifficultyColors["impossible"];
  3247. elseif ( levelDiff >= 3 ) then
  3248. return QuestDifficultyColors["verydifficult"];
  3249. elseif ( levelDiff >= -2 ) then
  3250. return QuestDifficultyColors["difficult"];
  3251. elseif ( -levelDiff <= GetQuestGreenRange() ) then
  3252. return QuestDifficultyColors["standard"];
  3253. else
  3254. return QuestDifficultyColors["trivial"];
  3255. end
  3256. end
  3257. -- takes in a table with r, g, and b entries and converts it to a color string
  3258. function ConvertRGBtoColorString(color)
  3259. local colorString = "|cff";
  3260. local r = color.r * 255;
  3261. local g = color.g * 255;
  3262. local b = color.b * 255;
  3263. colorString = colorString..string.format("%2x%2x%2x", r, g, b);
  3264. return colorString;
  3265. end
  3266. function GetDungeonNameWithDifficulty(name, difficultyName)
  3267. name = name or "";
  3268. if ( difficultyName == "" ) then
  3269. name = NORMAL_FONT_COLOR_CODE..name..FONT_COLOR_CODE_CLOSE;
  3270. else
  3271. name = NORMAL_FONT_COLOR_CODE..format(DUNGEON_NAME_WITH_DIFFICULTY, name, difficultyName)..FONT_COLOR_CODE_CLOSE;
  3272. end
  3273. return name;
  3274. end
  3275. -- Animated shine stuff --
  3276. function AnimatedShine_Start(shine, r, g, b)
  3277. if ( not tContains(SHINES_TO_ANIMATE, shine) ) then
  3278. shine.timer = 0;
  3279. tinsert(SHINES_TO_ANIMATE, shine);
  3280. end
  3281. local shineName = shine:GetName();
  3282. _G[shineName.."Shine1"]:Show();
  3283. _G[shineName.."Shine2"]:Show();
  3284. _G[shineName.."Shine3"]:Show();
  3285. _G[shineName.."Shine4"]:Show();
  3286. if ( r ) then
  3287. _G[shineName.."Shine1"]:SetVertexColor(r, g, b);
  3288. _G[shineName.."Shine2"]:SetVertexColor(r, g, b);
  3289. _G[shineName.."Shine3"]:SetVertexColor(r, g, b);
  3290. _G[shineName.."Shine4"]:SetVertexColor(r, g, b);
  3291. end
  3292. end
  3293. function AnimatedShine_Stop(shine)
  3294. tDeleteItem(SHINES_TO_ANIMATE, shine);
  3295. local shineName = shine:GetName();
  3296. _G[shineName.."Shine1"]:Hide();
  3297. _G[shineName.."Shine2"]:Hide();
  3298. _G[shineName.."Shine3"]:Hide();
  3299. _G[shineName.."Shine4"]:Hide();
  3300. end
  3301. function AnimatedShine_OnUpdate(elapsed)
  3302. local shine1, shine2, shine3, shine4;
  3303. local speed = 2.5;
  3304. local parent, distance;
  3305. for index, value in pairs(SHINES_TO_ANIMATE) do
  3306. shine1 = _G[value:GetName().."Shine1"];
  3307. shine2 = _G[value:GetName().."Shine2"];
  3308. shine3 = _G[value:GetName().."Shine3"];
  3309. shine4 = _G[value:GetName().."Shine4"];
  3310. value.timer = value.timer+elapsed;
  3311. if ( value.timer > speed*4 ) then
  3312. value.timer = 0;
  3313. end
  3314. parent = _G[value:GetName().."Shine"];
  3315. distance = parent:GetWidth();
  3316. if ( value.timer <= speed ) then
  3317. shine1:SetPoint("CENTER", parent, "TOPLEFT", value.timer/speed*distance, 0);
  3318. shine2:SetPoint("CENTER", parent, "BOTTOMRIGHT", -value.timer/speed*distance, 0);
  3319. shine3:SetPoint("CENTER", parent, "TOPRIGHT", 0, -value.timer/speed*distance);
  3320. shine4:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, value.timer/speed*distance);
  3321. elseif ( value.timer <= speed*2 ) then
  3322. shine1:SetPoint("CENTER", parent, "TOPRIGHT", 0, -(value.timer-speed)/speed*distance);
  3323. shine2:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, (value.timer-speed)/speed*distance);
  3324. shine3:SetPoint("CENTER", parent, "BOTTOMRIGHT", -(value.timer-speed)/speed*distance, 0);
  3325. shine4:SetPoint("CENTER", parent, "TOPLEFT", (value.timer-speed)/speed*distance, 0);
  3326. elseif ( value.timer <= speed*3 ) then
  3327. shine1:SetPoint("CENTER", parent, "BOTTOMRIGHT", -(value.timer-speed*2)/speed*distance, 0);
  3328. shine2:SetPoint("CENTER", parent, "TOPLEFT", (value.timer-speed*2)/speed*distance, 0);
  3329. shine3:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, (value.timer-speed*2)/speed*distance);
  3330. shine4:SetPoint("CENTER", parent, "TOPRIGHT", 0, -(value.timer-speed*2)/speed*distance);
  3331. else
  3332. shine1:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, (value.timer-speed*3)/speed*distance);
  3333. shine2:SetPoint("CENTER", parent, "TOPRIGHT", 0, -(value.timer-speed*3)/speed*distance);
  3334. shine3:SetPoint("CENTER", parent, "TOPLEFT", (value.timer-speed*3)/speed*distance, 0);
  3335. shine4:SetPoint("CENTER", parent, "BOTTOMRIGHT", -(value.timer-speed*3)/speed*distance, 0);
  3336. end
  3337. end
  3338. end
  3339. -- Autocast shine stuff --
  3340. AUTOCAST_SHINE_R = .95;
  3341. AUTOCAST_SHINE_G = .95;
  3342. AUTOCAST_SHINE_B = .32;
  3343. AUTOCAST_SHINE_SPEEDS = { 2, 4, 6, 8 };
  3344. AUTOCAST_SHINE_TIMERS = { 0, 0, 0, 0 };
  3345. local AUTOCAST_SHINES = {};
  3346. function AutoCastShine_OnLoad(self)
  3347. self.sparkles = {};
  3348. local name = self:GetName();
  3349. for i = 1, 16 do
  3350. tinsert(self.sparkles, _G[name .. i]);
  3351. end
  3352. end
  3353. function AutoCastShine_AutoCastStart(button, r, g, b)
  3354. if ( AUTOCAST_SHINES[button] ) then
  3355. return;
  3356. end
  3357. AUTOCAST_SHINES[button] = true;
  3358. if ( not r ) then
  3359. r, g, b = AUTOCAST_SHINE_R, AUTOCAST_SHINE_G, AUTOCAST_SHINE_B;
  3360. end
  3361. for _, sparkle in next, button.sparkles do
  3362. sparkle:Show();
  3363. sparkle:SetVertexColor(r, g, b);
  3364. end
  3365. end
  3366. function AutoCastShine_AutoCastStop(button)
  3367. AUTOCAST_SHINES[button] = nil;
  3368. for _, sparkle in next, button.sparkles do
  3369. sparkle:Hide();
  3370. end
  3371. end
  3372. function AutoCastShine_OnUpdate(self, elapsed)
  3373. for i in next, AUTOCAST_SHINE_TIMERS do
  3374. AUTOCAST_SHINE_TIMERS[i] = AUTOCAST_SHINE_TIMERS[i] + elapsed;
  3375. if ( AUTOCAST_SHINE_TIMERS[i] > AUTOCAST_SHINE_SPEEDS[i]*4 ) then
  3376. AUTOCAST_SHINE_TIMERS[i] = 0;
  3377. end
  3378. end
  3379. for button in next, AUTOCAST_SHINES do
  3380. self = button;
  3381. local parent, distance = self, self:GetWidth();
  3382. -- This is local to this function to save a lookup. If you need to use it elsewhere, might wanna make it global and use a local reference.
  3383. local AUTOCAST_SHINE_SPACING = 6;
  3384. for i = 1, 4 do
  3385. local timer = AUTOCAST_SHINE_TIMERS[i];
  3386. local speed = AUTOCAST_SHINE_SPEEDS[i];
  3387. if ( timer <= speed ) then
  3388. local basePosition = timer/speed*distance;
  3389. self.sparkles[0+i]:SetPoint("CENTER", parent, "TOPLEFT", basePosition, 0);
  3390. self.sparkles[4+i]:SetPoint("CENTER", parent, "BOTTOMRIGHT", -basePosition, 0);
  3391. self.sparkles[8+i]:SetPoint("CENTER", parent, "TOPRIGHT", 0, -basePosition);
  3392. self.sparkles[12+i]:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, basePosition);
  3393. elseif ( timer <= speed*2 ) then
  3394. local basePosition = (timer-speed)/speed*distance;
  3395. self.sparkles[0+i]:SetPoint("CENTER", parent, "TOPRIGHT", 0, -basePosition);
  3396. self.sparkles[4+i]:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, basePosition);
  3397. self.sparkles[8+i]:SetPoint("CENTER", parent, "BOTTOMRIGHT", -basePosition, 0);
  3398. self.sparkles[12+i]:SetPoint("CENTER", parent, "TOPLEFT", basePosition, 0);
  3399. elseif ( timer <= speed*3 ) then
  3400. local basePosition = (timer-speed*2)/speed*distance;
  3401. self.sparkles[0+i]:SetPoint("CENTER", parent, "BOTTOMRIGHT", -basePosition, 0);
  3402. self.sparkles[4+i]:SetPoint("CENTER", parent, "TOPLEFT", basePosition, 0);
  3403. self.sparkles[8+i]:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, basePosition);
  3404. self.sparkles[12+i]:SetPoint("CENTER", parent, "TOPRIGHT", 0, -basePosition);
  3405. else
  3406. local basePosition = (timer-speed*3)/speed*distance;
  3407. self.sparkles[0+i]:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, basePosition);
  3408. self.sparkles[4+i]:SetPoint("CENTER", parent, "TOPRIGHT", 0, -basePosition);
  3409. self.sparkles[8+i]:SetPoint("CENTER", parent, "TOPLEFT", basePosition, 0);
  3410. self.sparkles[12+i]:SetPoint("CENTER", parent, "BOTTOMRIGHT", -basePosition, 0);
  3411. end
  3412. end
  3413. end
  3414. end
  3415. function ConsolePrint(...)
  3416. ConsoleAddMessage(strjoin(" ", tostringall(...)));
  3417. end
  3418. function GetTexCoordsByGrid(xOffset, yOffset, textureWidth, textureHeight, gridWidth, gridHeight)
  3419. local widthPerGrid = gridWidth/textureWidth;
  3420. local heightPerGrid = gridHeight/textureHeight;
  3421. return (xOffset-1)*widthPerGrid, (xOffset)*widthPerGrid, (yOffset-1)*heightPerGrid, (yOffset)*heightPerGrid;
  3422. end
  3423. function LFD_IsEmpowered()
  3424. --Solo players are always empowered.
  3425. if ( not IsInGroup() ) then
  3426. return true;
  3427. end
  3428. --The leader may always queue/dequeue
  3429. if ( UnitIsGroupLeader("player") ) then
  3430. return true;
  3431. end
  3432. --In DF groups, anyone may queue/dequeue. In RF groups, the leader or assistants may queue/dequeue.
  3433. if ( HasLFGRestrictions() and (not IsInRaid() or UnitIsGroupAssistant("player")) ) then
  3434. return true;
  3435. end
  3436. return false;
  3437. end
  3438. function RaidBrowser_IsEmpowered()
  3439. return (not IsInGroup()) or UnitIsGroupLeader("player");
  3440. end
  3441. function GetLFGMode(category)
  3442. local proposalExists, id, typeID, subtypeID, name, texture, role, hasResponded, totalEncounters, completedEncounters, numMembers, isLeader, isHoliday, proposalCategory = GetLFGProposal();
  3443. local inParty, joined, queued, noPartialClear, achievements, lfgComment, slotCount = GetLFGInfoServer(category);
  3444. local roleCheckInProgress, slots, members, roleUpdateCategory = GetLFGRoleUpdate();
  3445. local partyCategory = nil;
  3446. local partySlot = GetPartyLFGID();
  3447. if ( partySlot ) then
  3448. partyCategory = GetLFGCategoryForID(partySlot);
  3449. end
  3450. local empoweredFunc = LFD_IsEmpowered;
  3451. if ( category == LE_LFG_CATEGORY_LFR ) then
  3452. empoweredFunc = RaidBrowser_IsEmpowered;
  3453. end
  3454. if ( proposalExists and not hasResponded and proposalCategory == category ) then
  3455. return "proposal", "unaccepted";
  3456. elseif ( proposalExists and proposalCategory == category ) then
  3457. return "proposal", "accepted";
  3458. elseif ( queued ) then
  3459. return "queued", (empoweredFunc() and "empowered" or "unempowered");
  3460. elseif ( roleCheckInProgress and roleUpdateCategory == category ) then
  3461. return "rolecheck";
  3462. elseif ( category == LE_LFG_CATEGORY_LFR and joined ) then
  3463. return "listed", (empoweredFunc() and "empowered" or "unempowered");
  3464. elseif ( joined ) then
  3465. return "suspended", (empoweredFunc() and "empowered" or "unempowered"); --We are "joined" to LFG, but not actually queued right now.
  3466. elseif ( IsInGroup() and IsPartyLFG() and partyCategory == category ) then
  3467. return "lfgparty";
  3468. elseif ( IsPartyLFG() and IsInLFGDungeon() and partyCategory == category ) then
  3469. return "abandonedInDungeon";
  3470. end
  3471. end
  3472. function IsLFGModeActive(category)
  3473. local partySlot = GetPartyLFGID();
  3474. local partyCategory = nil;
  3475. if ( partySlot ) then
  3476. partyCategory = GetLFGCategoryForID(partySlot);
  3477. end
  3478. if ( partyCategory == category ) then
  3479. return true;
  3480. end
  3481. return false;
  3482. end
  3483. --Like date(), but localizes AM/PM. In the future, could also localize other stuff.
  3484. function BetterDate(formatString, timeVal)
  3485. local dateTable = date("*t", timeVal);
  3486. local amString = (dateTable.hour >= 12) and TIMEMANAGER_PM or TIMEMANAGER_AM;
  3487. --First, we'll replace %p with the appropriate AM or PM.
  3488. formatString = gsub(formatString, "^%%p", amString) --Replaces %p at the beginning of the string with the am/pm token
  3489. formatString = gsub(formatString, "([^%%])%%p", "%1"..amString); -- Replaces %p anywhere else in the string, but doesn't replace %%p (since the first % escapes the second)
  3490. return date(formatString, timeVal);
  3491. end
  3492. function GMError(...)
  3493. if ( IsGMClient() ) then
  3494. error(...);
  3495. end
  3496. end
  3497. function SetLargeGuildTabardTextures(unit, emblemTexture, backgroundTexture, borderTexture, tabardData)
  3498. -- texure dimensions are 1024x1024, icon dimensions are 64x64
  3499. local emblemSize, columns, offset;
  3500. if ( emblemTexture ) then
  3501. emblemSize = 64 / 1024;
  3502. columns = 16
  3503. offset = 0;
  3504. emblemTexture:SetTexture("Interface\\GuildFrame\\GuildEmblemsLG_01");
  3505. end
  3506. SetGuildTabardTextures(emblemSize, columns, offset, unit, emblemTexture, backgroundTexture, borderTexture, tabardData);
  3507. end
  3508. function SetSmallGuildTabardTextures(unit, emblemTexture, backgroundTexture, borderTexture, tabardData)
  3509. -- texure dimensions are 256x256, icon dimensions are 16x16, centered in 18x18 cells
  3510. local emblemSize, columns, offset;
  3511. if ( emblemTexture ) then
  3512. emblemSize = 18 / 256;
  3513. columns = 14;
  3514. offset = 1 / 256;
  3515. emblemTexture:SetTexture("Interface\\GuildFrame\\GuildEmblems_01");
  3516. end
  3517. SetGuildTabardTextures(emblemSize, columns, offset, unit, emblemTexture, backgroundTexture, borderTexture, tabardData);
  3518. end
  3519. function SetDoubleGuildTabardTextures(unit, leftEmblemTexture, rightEmblemTexture, backgroundTexture, borderTexture, tabardData)
  3520. if ( leftEmblemTexture and rightEmblemTexture ) then
  3521. SetGuildTabardTextures(nil, nil, nil, unit, leftEmblemTexture, backgroundTexture, borderTexture, tabardData);
  3522. rightEmblemTexture:SetTexture(leftEmblemTexture:GetTexture());
  3523. rightEmblemTexture:SetVertexColor(leftEmblemTexture:GetVertexColor());
  3524. end
  3525. end
  3526. function SetGuildTabardTextures(emblemSize, columns, offset, unit, emblemTexture, backgroundTexture, borderTexture, tabardData)
  3527. local bkgR, bkgG, bkgB, borderR, borderG, borderB, emblemR, emblemG, emblemB, emblemFilename;
  3528. if ( tabardData ) then
  3529. bkgR = tabardData[1];
  3530. bkgG = tabardData[2];
  3531. bkgB = tabardData[3];
  3532. borderR = tabardData[4];
  3533. borderG = tabardData[5];
  3534. borderB = tabardData[6];
  3535. emblemR = tabardData[7];
  3536. emblemG = tabardData[8];
  3537. emblemB = tabardData[9];
  3538. emblemFilename = tabardData[10];
  3539. else
  3540. bkgR, bkgG, bkgB, borderR, borderG, borderB, emblemR, emblemG, emblemB, emblemFilename = GetGuildLogoInfo(unit);
  3541. end
  3542. if ( emblemFilename ) then
  3543. if ( backgroundTexture ) then
  3544. backgroundTexture:SetVertexColor(bkgR / 255, bkgG / 255, bkgB / 255);
  3545. end
  3546. if ( borderTexture ) then
  3547. borderTexture:SetVertexColor(borderR / 255, borderG / 255, borderB / 255);
  3548. end
  3549. if ( emblemSize ) then
  3550. local index = emblemFilename:match("([%d]+)");
  3551. if ( index) then
  3552. index = tonumber(index);
  3553. local xCoord = mod(index, columns) * emblemSize;
  3554. local yCoord = floor(index / columns) * emblemSize;
  3555. emblemTexture:SetTexCoord(xCoord + offset, xCoord + emblemSize - offset, yCoord + offset, yCoord + emblemSize - offset);
  3556. end
  3557. emblemTexture:SetVertexColor(emblemR / 255, emblemG / 255, emblemB / 255);
  3558. elseif ( emblemTexture ) then
  3559. emblemTexture:SetTexture(emblemFilename);
  3560. emblemTexture:SetVertexColor(emblemR / 255, emblemG / 255, emblemB / 255);
  3561. end
  3562. else
  3563. -- tabard lacks design
  3564. if ( backgroundTexture ) then
  3565. backgroundTexture:SetVertexColor(0.2245, 0.2088, 0.1794);
  3566. end
  3567. if ( borderTexture ) then
  3568. borderTexture:SetVertexColor(0.2, 0.2, 0.2);
  3569. end
  3570. if ( emblemTexture ) then
  3571. if ( emblemSize ) then
  3572. if ( emblemSize == 18 / 256 ) then
  3573. emblemTexture:SetTexture("Interface\\GuildFrame\\GuildLogo-NoLogoSm");
  3574. else
  3575. emblemTexture:SetTexture("Interface\\GuildFrame\\GuildLogo-NoLogo");
  3576. end
  3577. emblemTexture:SetTexCoord(0, 1, 0, 1);
  3578. emblemTexture:SetVertexColor(1, 1, 1, 1);
  3579. else
  3580. emblemTexture:SetTexture("");
  3581. end
  3582. end
  3583. end
  3584. end
  3585. function GetDisplayedAllyFrames()
  3586. local useCompact = GetCVarBool("useCompactPartyFrames")
  3587. if ( IsActiveBattlefieldArena() and not useCompact ) then
  3588. return "party";
  3589. elseif ( IsInGroup() and (IsInRaid() or useCompact) ) then
  3590. return "raid";
  3591. elseif ( IsInGroup() ) then
  3592. return "party";
  3593. else
  3594. return nil;
  3595. end
  3596. end
  3597. function ReverseQuestObjective(text, objectiveType)
  3598. if ( objectiveType == "spell" ) then
  3599. return text;
  3600. end
  3601. local _, _, arg1, arg2 = string.find(text, "(.*):%s(.*)");
  3602. if ( arg1 and arg2 ) then
  3603. return arg2.." "..arg1;
  3604. else
  3605. return text;
  3606. end
  3607. end
  3608. local displayedCapMessage = false;
  3609. function TrialAccountCapReached_Inform(capType)
  3610. if ( displayedCapMessage or not IsTrialAccount() ) then
  3611. return;
  3612. end
  3613. local info = ChatTypeInfo.SYSTEM;
  3614. if ( capType == "level" ) then
  3615. DEFAULT_CHAT_FRAME:AddMessage(TRIAL_ACCOUNT_LEVEL_CAP_REACHED, info.r, info.g, info.b);
  3616. elseif ( capType == "money" ) then
  3617. DEFAULT_CHAT_FRAME:AddMessage(TRIAL_ACCOUNT_MONEY_CAP_REACHED, info.r, info.g, info.b);
  3618. end
  3619. displayedCapMessage = true;
  3620. end
  3621. function AbbreviateLargeNumbers(value)
  3622. local strLen = strlen(value);
  3623. local retString = value;
  3624. if ( strLen > 8 ) then
  3625. retString = string.sub(value, 1, -7)..SECOND_NUMBER_CAP;
  3626. elseif ( strLen > 5 ) then
  3627. retString = string.sub(value, 1, -4)..FIRST_NUMBER_CAP;
  3628. elseif (strLen > 3 ) then
  3629. retString = BreakUpLargeNumbers(value);
  3630. end
  3631. return retString;
  3632. end
  3633. function BreakUpLargeNumbers(value)
  3634. local retString = "";
  3635. if ( value < 1000 ) then
  3636. if ( (value - math.floor(value)) == 0) then
  3637. return value;
  3638. end
  3639. local decimal = (math.floor(value*100));
  3640. retString = string.sub(decimal, 1, -3);
  3641. retString = retString..DECIMAL_SEPERATOR;
  3642. retString = retString..string.sub(decimal, -2);
  3643. return retString;
  3644. end
  3645. value = math.floor(value);
  3646. local strLen = strlen(value);
  3647. if ( GetCVarBool("breakUpLargeNumbers") ) then
  3648. if ( strLen > 6 ) then
  3649. retString = string.sub(value, 1, -7)..LARGE_NUMBER_SEPERATOR;
  3650. end
  3651. if ( strLen > 3 ) then
  3652. retString = retString..string.sub(value, -6, -4)..LARGE_NUMBER_SEPERATOR;
  3653. end
  3654. retString = retString..string.sub(value, -3, -1);
  3655. else
  3656. retString = value;
  3657. end
  3658. return retString;
  3659. end
  3660. function GetTimeStringFromSeconds(timeAmount, hasMS)
  3661. local seconds, ms;
  3662. -- milliseconds
  3663. if ( hasMS ) then
  3664. seconds = floor(timeAmount / 1000);
  3665. ms = timeAmount - seconds * 1000;
  3666. else
  3667. seconds = timeAmount;
  3668. end
  3669. local hours = floor(seconds / 3600);
  3670. local minutes = floor((seconds / 60) - (hours * 60));
  3671. seconds = seconds - hours * 3600 - minutes * 60;
  3672. -- if ( hasMS ) then
  3673. -- return format(HOURS_MINUTES_SECONDS_MILLISECONDS, hours, minutes, seconds, ms);
  3674. -- else
  3675. return format(HOURS_MINUTES_SECONDS, hours, minutes, seconds);
  3676. -- end
  3677. end
  3678. function ConfirmOrLeaveLFGParty()
  3679. if ( not IsInGroup(LE_PARTY_CATEGORY_INSTANCE) ) then
  3680. return;
  3681. end
  3682. if ( IsPartyLFG() and not IsLFGComplete() ) then
  3683. StaticPopup_Show("CONFIRM_LEAVE_INSTANCE_PARTY");
  3684. else
  3685. LeaveParty();
  3686. end
  3687. end
  3688. function ConfirmOrLeaveBattlefield()
  3689. if ( GetBattlefieldWinner() ) then
  3690. LeaveBattlefield();
  3691. else
  3692. StaticPopup_Show("CONFIRM_LEAVE_BATTLEFIELD");
  3693. end
  3694. end