UIParent.lua

UIParent.lua (8.3.0.34220; unchanged since 8.3.0.33169)
  1. TOOLTIP_UPDATE_TIME = 0.2;
  2. BOSS_FRAME_CASTBAR_HEIGHT = 16;
  3. -- Alpha animation stuff
  4. FADEFRAMES = {};
  5. FLASHFRAMES = {};
  6. -- Pulsing stuff
  7. PULSEBUTTONS = {};
  8. -- Shine animation
  9. SHINES_TO_ANIMATE = {};
  10. -- Macros
  11. MAX_ACCOUNT_MACROS = 120;
  12. MAX_CHARACTER_MACROS = 18;
  13. -- UIPanel Management constants
  14. UIPANEL_SKIP_SET_POINT = true;
  15. UIPANEL_DO_SET_POINT = nil;
  16. UIPANEL_VALIDATE_CURRENT_FRAME = true;
  17. -- Per panel settings
  18. UIPanelWindows = {};
  19. --Center Menu Frames
  20. UIPanelWindows["GameMenuFrame"] = { area = "center", pushable = 0, whileDead = 1 };
  21. UIPanelWindows["VideoOptionsFrame"] = { area = "center", pushable = 0, whileDead = 1 };
  22. UIPanelWindows["AudioOptionsFrame"] = { area = "center", pushable = 0, whileDead = 1 };
  23. UIPanelWindows["InterfaceOptionsFrame"] = { area = "center", pushable = 0, whileDead = 1 };
  24. UIPanelWindows["HelpFrame"] = { area = "center", pushable = 0, whileDead = 1 };
  25. -- Frames using the new Templates
  26. UIPanelWindows["CharacterFrame"] = { area = "left", pushable = 3, whileDead = 1};
  27. UIPanelWindows["SpellBookFrame"] = { area = "left", pushable = 1, whileDead = 1, width = 575, height = 545 };
  28. UIPanelWindows["TaxiFrame"] = { area = "left", pushable = 0, width = 605, height = 580, showFailedFunc = CloseTaxiMap };
  29. UIPanelWindows["PVPUIFrame"] = { area = "left", pushable = 0, whileDead = 1, width = 563};
  30. UIPanelWindows["PVPBannerFrame"] = { area = "left", pushable = 1};
  31. UIPanelWindows["PetStableFrame"] = { area = "left", pushable = 0};
  32. UIPanelWindows["PVEFrame"] = { area = "left", pushable = 1, whileDead = 1 };
  33. UIPanelWindows["EncounterJournal"] = { area = "left", pushable = 0, whileDead = 1, width = 830};
  34. UIPanelWindows["CollectionsJournal"] = { area = "left", pushable = 0, whileDead = 1, width = 733};
  35. UIPanelWindows["TradeFrame"] = { area = "left", pushable = 1};
  36. UIPanelWindows["LootFrame"] = { area = "left", pushable = 7};
  37. UIPanelWindows["MerchantFrame"] = { area = "left", pushable = 0};
  38. UIPanelWindows["TabardFrame"] = { area = "left", pushable = 0};
  39. UIPanelWindows["PVPBannerFrame"] = { area = "left", pushable = 1};
  40. UIPanelWindows["MailFrame"] = { area = "left", pushable = 0};
  41. UIPanelWindows["BankFrame"] = { area = "left", pushable = 6, width = 425 };
  42. UIPanelWindows["QuestLogPopupDetailFrame"] = { area = "left", pushable = 0, whileDead = 1 };
  43. UIPanelWindows["QuestFrame"] = { area = "left", pushable = 0};
  44. UIPanelWindows["GuildRegistrarFrame"] = { area = "left", pushable = 0};
  45. UIPanelWindows["GossipFrame"] = { area = "left", pushable = 0};
  46. UIPanelWindows["DressUpFrame"] = { area = "left", pushable = 2};
  47. UIPanelWindows["PetitionFrame"] = { area = "left", pushable = 0};
  48. UIPanelWindows["ItemTextFrame"] = { area = "left", pushable = 0};
  49. UIPanelWindows["FriendsFrame"] = { area = "left", pushable = 0, whileDead = 1 };
  50. UIPanelWindows["RaidParentFrame"] = { area = "left", pushable = 1, whileDead = 1 };
  51. UIPanelWindows["RaidBrowserFrame"] = { area = "left", pushable = 1, };
  52. UIPanelWindows["DeathRecapFrame"] = { area = "center", pushable = 0, whileDead = 1, allowOtherPanels = 1};
  53. UIPanelWindows["WardrobeFrame"] = { area = "left", pushable = 0, width = 965 };
  54. UIPanelWindows["AlliedRacesFrame"] = { area = "left", pushable = 1, whileDead = 1 };
  55. UIPanelWindows["GuildControlUI"] = { area = "left", pushable = 1, whileDead = 1, yoffset = 4, };
  56. UIPanelWindows["CommunitiesFrame"] = { area = "left", pushable = 1, whileDead = 1 };
  57. UIPanelWindows["CommunitiesGuildLogFrame"] = { area = "left", pushable = 1, whileDead = 1, yoffset = 4, };
  58. UIPanelWindows["CommunitiesGuildTextEditFrame"] = { area = "left", pushable = 1, whileDead = 1 };
  59. UIPanelWindows["CommunitiesGuildRecruitmentFrame"] = { area = "left", pushable = 1, whileDead = 1 };
  60. UIPanelWindows["CommunitiesGuildNewsFiltersFrame"] = { area = "left", pushable = 1, whileDead = 1 };
  61. UIPanelWindows["ClubFinderGuildRecruitmentDialog"] = { area = "left", pushable = 1, whileDead = 1 };
  62. -- Frames NOT using the new Templates
  63. UIPanelWindows["CinematicFrame"] = { area = "full", pushable = 0, xoffset = -16, yoffset = 12, whileDead = 1 };
  64. UIPanelWindows["ChatConfigFrame"] = { area = "center", pushable = 0, xoffset = -16, yoffset = 12, whileDead = 1 };
  65. UIPanelWindows["PVPMatchScoreboard"] = { area = "center", pushable = 0, xoffset = -16, yoffset = 12, whileDead = 1, ignoreControlLost = true, };
  66. UIPanelWindows["PVPMatchResults"] = { area = "center", pushable = 0, xoffset = -16, yoffset = 12, whileDead = 1, ignoreControlLost = true, };
  67. UIPanelWindows["QuestChoiceFrame"] = { area = "center", pushable = 0, xoffset = -16, yoffset = 12, whileDead = 0, allowOtherPanels = 1 };
  68. UIPanelWindows["WarboardQuestChoiceFrame"] = { area = "center", pushable = 0, xoffset = -16, yoffset = 12, whileDead = 0, allowOtherPanels = 1 };
  69. UIPanelWindows["GarrisonBuildingFrame"] = { area = "center", pushable = 0, whileDead = 1, width = 1002, allowOtherPanels = 1};
  70. UIPanelWindows["GarrisonMissionFrame"] = { area = "center", pushable = 0, whileDead = 1, checkFit = 1, allowOtherPanels = 1, extraWidth = 20, extraHeight = 100 };
  71. UIPanelWindows["GarrisonShipyardFrame"] = { area = "center", pushable = 0, whileDead = 1, checkFit = 1, allowOtherPanels = 1, extraWidth = 20, extraHeight = 100 };
  72. UIPanelWindows["GarrisonLandingPage"] = { area = "left", pushable = 1, whileDead = 1, width = 830, yoffset = 9, allowOtherPanels = 1};
  73. UIPanelWindows["GarrisonMonumentFrame"] = { area = "center", pushable = 0, whileDead = 1, width = 333, allowOtherPanels = 1};
  74. UIPanelWindows["GarrisonRecruiterFrame"] = { area = "left", pushable = 0};
  75. UIPanelWindows["GarrisonRecruitSelectFrame"] = { area = "center", pushable = 0};
  76. UIPanelWindows["OrderHallMissionFrame"] = { area = "center", pushable = 0, whileDead = 1, checkFit = 1, allowOtherPanels = 1, extraWidth = 20, extraHeight = 100 };
  77. UIPanelWindows["OrderHallTalentFrame"] = { area = "left", pushable = 0, xoffset = 16};
  78. UIPanelWindows["ChallengesKeystoneFrame"] = { area = "center", pushable = 0};
  79. UIPanelWindows["BFAMissionFrame"] = { area = "center", pushable = 0, whileDead = 1, checkFit = 1, allowOtherPanels = 1, extraWidth = 20, extraHeight = 100 };
  80. local function GetUIPanelWindowInfo(frame, name)
  81. if ( not frame:GetAttribute("UIPanelLayout-defined") ) then
  82. local info = UIPanelWindows[frame:GetName()];
  83. if ( not info ) then
  84. return;
  85. end
  86. frame:SetAttribute("UIPanelLayout-defined", true);
  87. for name,value in pairs(info) do
  88. frame:SetAttribute("UIPanelLayout-"..name, value);
  89. end
  90. end
  91. return frame:GetAttribute("UIPanelLayout-"..name);
  92. end
  93. function SetUIPanelAttribute(frame, name, value)
  94. local info = UIPanelWindows[frame:GetName()];
  95. if ( not info ) then
  96. return;
  97. end
  98. if ( not frame:GetAttribute("UIPanelLayout-defined") ) then
  99. frame:SetAttribute("UIPanelLayout-defined", true);
  100. for name,value in pairs(info) do
  101. frame:SetAttribute("UIPanelLayout-"..name, value);
  102. end
  103. end
  104. frame:SetAttribute("UIPanelLayout-"..name, value);
  105. end
  106. -- 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.
  107. UIChildWindows = {
  108. "OpenMailFrame",
  109. "GuildMemberDetailFrame",
  110. "TokenFramePopup",
  111. "GuildBankPopupFrame",
  112. "GearManagerDialog",
  113. };
  114. function UpdateUIParentRelativeToDebugMenu()
  115. local debugMenuOffset = DebugMenu and DebugMenu.IsVisible() and -DebugMenu.GetMenuHeight() or 0;
  116. local revealTimeTrackOffset = C_Reveal and C_Reveal:IsCapturing() and -C_Reveal:GetTimeTrackHeight() or 0;
  117. local topOffset = debugMenuOffset + revealTimeTrackOffset;
  118. UIParent:SetPoint("TOPLEFT", 0, topOffset);
  119. end
  120. UISpecialFrames = {
  121. "ItemRefTooltip",
  122. "ColorPickerFrame",
  123. "FloatingPetBattleAbilityTooltip",
  124. "FloatingGarrisonFollowerTooltip",
  125. "FloatingGarrisonShipyardFollowerTooltip"
  126. };
  127. UIMenus = {
  128. "ChatMenu",
  129. "EmoteMenu",
  130. "LanguageMenu",
  131. "DropDownList1",
  132. "DropDownList2",
  133. };
  134. ITEM_QUALITY_COLORS = { };
  135. for i = 0, NUM_LE_ITEM_QUALITYS - 1 do
  136. local r, g, b = GetItemQualityColor(i);
  137. local color = CreateColor(r, g, b, 1);
  138. ITEM_QUALITY_COLORS[i] = { r = r, g = g, b = b, hex = color:GenerateHexColorMarkup(), color = color };
  139. end
  140. WORLD_QUEST_QUALITY_COLORS = {
  141. [LE_WORLD_QUEST_QUALITY_COMMON] = ITEM_QUALITY_COLORS[LE_ITEM_QUALITY_COMMON];
  142. [LE_WORLD_QUEST_QUALITY_RARE] = ITEM_QUALITY_COLORS[LE_ITEM_QUALITY_RARE];
  143. [LE_WORLD_QUEST_QUALITY_EPIC] = ITEM_QUALITY_COLORS[LE_ITEM_QUALITY_EPIC];
  144. };
  145. -- Protecting from addons since we use this in GetScaledCursorDelta which is used in secure code.
  146. local _UIParentGetEffectiveScale;
  147. local _UIParentRef;
  148. function UIParent_OnLoad(self)
  149. _UIParentGetEffectiveScale = self.GetEffectiveScale;
  150. _UIParentRef = self;
  151. self:RegisterEvent("PLAYER_LOGIN");
  152. self:RegisterEvent("PLAYER_DEAD");
  153. self:RegisterEvent("SELF_RES_SPELL_CHANGED");
  154. self:RegisterEvent("PLAYER_ALIVE");
  155. self:RegisterEvent("PLAYER_UNGHOST");
  156. self:RegisterEvent("RESURRECT_REQUEST");
  157. self:RegisterEvent("PLAYER_SKINNED");
  158. self:RegisterEvent("TRADE_REQUEST");
  159. self:RegisterEvent("CHANNEL_INVITE_REQUEST");
  160. self:RegisterEvent("CHANNEL_PASSWORD_REQUEST");
  161. self:RegisterEvent("PARTY_INVITE_REQUEST");
  162. self:RegisterEvent("PARTY_INVITE_CANCEL");
  163. self:RegisterEvent("GUILD_INVITE_REQUEST");
  164. self:RegisterEvent("GUILD_INVITE_CANCEL");
  165. self:RegisterEvent("PLAYER_CAMPING");
  166. self:RegisterEvent("PLAYER_QUITING");
  167. self:RegisterEvent("LOGOUT_CANCEL");
  168. self:RegisterEvent("LOOT_BIND_CONFIRM");
  169. self:RegisterEvent("EQUIP_BIND_CONFIRM");
  170. self:RegisterEvent("EQUIP_BIND_TRADEABLE_CONFIRM");
  171. self:RegisterEvent("USE_BIND_CONFIRM");
  172. self:RegisterEvent("USE_NO_REFUND_CONFIRM");
  173. self:RegisterEvent("CONFIRM_BEFORE_USE");
  174. self:RegisterEvent("DELETE_ITEM_CONFIRM");
  175. self:RegisterEvent("QUEST_ACCEPT_CONFIRM");
  176. self:RegisterEvent("QUEST_LOG_UPDATE");
  177. self:RegisterEvent("UNIT_QUEST_LOG_CHANGED");
  178. self:RegisterEvent("CURSOR_UPDATE");
  179. self:RegisterEvent("LOCALPLAYER_PET_RENAMED");
  180. self:RegisterEvent("PLAYER_ENTERING_WORLD");
  181. self:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED");
  182. self:RegisterEvent("MIRROR_TIMER_START");
  183. self:RegisterEvent("DUEL_REQUESTED");
  184. self:RegisterEvent("DUEL_OUTOFBOUNDS");
  185. self:RegisterEvent("DUEL_INBOUNDS");
  186. self:RegisterEvent("DUEL_FINISHED");
  187. self:RegisterEvent("PET_BATTLE_PVP_DUEL_REQUESTED");
  188. self:RegisterEvent("PET_BATTLE_QUEUE_PROPOSE_MATCH");
  189. self:RegisterEvent("PET_BATTLE_QUEUE_PROPOSAL_DECLINED");
  190. self:RegisterEvent("PET_BATTLE_QUEUE_PROPOSAL_ACCEPTED");
  191. self:RegisterEvent("PET_BATTLE_PVP_DUEL_REQUEST_CANCEL");
  192. self:RegisterEvent("TRADE_REQUEST_CANCEL");
  193. self:RegisterEvent("CONFIRM_XP_LOSS");
  194. self:RegisterEvent("CORPSE_IN_RANGE");
  195. self:RegisterEvent("CORPSE_IN_INSTANCE");
  196. self:RegisterEvent("CORPSE_OUT_OF_RANGE");
  197. self:RegisterEvent("AREA_SPIRIT_HEALER_IN_RANGE");
  198. self:RegisterEvent("AREA_SPIRIT_HEALER_OUT_OF_RANGE");
  199. self:RegisterEvent("BIND_ENCHANT");
  200. self:RegisterEvent("ACTION_WILL_BIND_ITEM");
  201. self:RegisterEvent("REPLACE_ENCHANT");
  202. self:RegisterEvent("TRADE_REPLACE_ENCHANT");
  203. self:RegisterEvent("END_BOUND_TRADEABLE");
  204. self:RegisterEvent("CURRENT_SPELL_CAST_CHANGED");
  205. self:RegisterEvent("MACRO_ACTION_BLOCKED");
  206. self:RegisterEvent("ADDON_ACTION_BLOCKED");
  207. self:RegisterEvent("MACRO_ACTION_FORBIDDEN");
  208. self:RegisterEvent("ADDON_ACTION_FORBIDDEN");
  209. self:RegisterEvent("PLAYER_CONTROL_LOST");
  210. self:RegisterEvent("PLAYER_CONTROL_GAINED");
  211. self:RegisterEvent("START_LOOT_ROLL");
  212. self:RegisterEvent("CONFIRM_LOOT_ROLL");
  213. self:RegisterEvent("CONFIRM_DISENCHANT_ROLL");
  214. self:RegisterEvent("INSTANCE_BOOT_START");
  215. self:RegisterEvent("INSTANCE_BOOT_STOP");
  216. self:RegisterEvent("INSTANCE_LOCK_START");
  217. self:RegisterEvent("INSTANCE_LOCK_STOP");
  218. self:RegisterEvent("INSTANCE_LOCK_WARNING");
  219. self:RegisterEvent("CONFIRM_TALENT_WIPE");
  220. self:RegisterEvent("CONFIRM_BINDER");
  221. self:RegisterEvent("CONFIRM_SUMMON");
  222. self:RegisterEvent("CANCEL_SUMMON");
  223. self:RegisterEvent("GOSSIP_CONFIRM");
  224. self:RegisterEvent("GOSSIP_CONFIRM_CANCEL");
  225. self:RegisterEvent("GOSSIP_ENTER_CODE");
  226. self:RegisterEvent("GOSSIP_CLOSED");
  227. self:RegisterEvent("BILLING_NAG_DIALOG");
  228. self:RegisterEvent("IGR_BILLING_NAG_DIALOG");
  229. self:RegisterEvent("VARIABLES_LOADED");
  230. self:RegisterEvent("GROUP_ROSTER_UPDATE");
  231. self:RegisterEvent("RAID_INSTANCE_WELCOME");
  232. self:RegisterEvent("RAISED_AS_GHOUL");
  233. self:RegisterEvent("SPELL_CONFIRMATION_PROMPT");
  234. self:RegisterEvent("SPELL_CONFIRMATION_TIMEOUT");
  235. self:RegisterEvent("SAVED_VARIABLES_TOO_LARGE");
  236. self:RegisterEvent("EXPERIMENTAL_CVAR_CONFIRMATION_NEEDED");
  237. self:RegisterEvent("BAG_OVERFLOW_WITH_FULL_INVENTORY");
  238. self:RegisterEvent("AUCTION_HOUSE_SCRIPT_DEPRECATED");
  239. self:RegisterEvent("LOADING_SCREEN_ENABLED");
  240. self:RegisterEvent("LOADING_SCREEN_DISABLED");
  241. -- Events for auction UI handling
  242. self:RegisterEvent("AUCTION_HOUSE_SHOW");
  243. self:RegisterEvent("AUCTION_HOUSE_CLOSED");
  244. self:RegisterEvent("AUCTION_HOUSE_DISABLED");
  245. -- Events for trainer UI handling
  246. self:RegisterEvent("TRAINER_SHOW");
  247. self:RegisterEvent("TRAINER_CLOSED");
  248. -- Events for trade skill UI handling
  249. self:RegisterEvent("TRADE_SKILL_SHOW");
  250. self:RegisterEvent("OBLITERUM_FORGE_SHOW");
  251. self:RegisterEvent("SCRAPPING_MACHINE_SHOW");
  252. -- Events for Item socketing UI
  253. self:RegisterEvent("SOCKET_INFO_UPDATE");
  254. -- Events for Artifact UI
  255. self:RegisterEvent("ARTIFACT_UPDATE");
  256. self:RegisterEvent("ARTIFACT_RESPEC_PROMPT");
  257. self:RegisterEvent("ARTIFACT_RELIC_FORGE_UPDATE");
  258. -- Events for Adventure Map UI
  259. self:RegisterEvent("ADVENTURE_MAP_OPEN");
  260. -- Events for taxi benchmarking
  261. self:RegisterEvent("ENABLE_TAXI_BENCHMARK");
  262. self:RegisterEvent("DISABLE_TAXI_BENCHMARK");
  263. -- Events for BarberShop Handling
  264. self:RegisterEvent("BARBER_SHOP_OPEN");
  265. self:RegisterEvent("BARBER_SHOP_CLOSE");
  266. -- Events for Guild bank UI
  267. self:RegisterEvent("GUILDBANKFRAME_OPENED");
  268. self:RegisterEvent("GUILDBANKFRAME_CLOSED");
  269. --Events for GMChatUI
  270. self:RegisterEvent("CHAT_MSG_WHISPER");
  271. -- Events for WoW Mouse
  272. self:RegisterEvent("WOW_MOUSE_NOT_FOUND");
  273. -- Events for talent wipes
  274. self:RegisterEvent("TALENTS_INVOLUNTARILY_RESET");
  275. -- Events for disabled specs
  276. self:RegisterEvent("SPEC_INVOLUNTARILY_CHANGED");
  277. -- Events for Archaeology
  278. self:RegisterEvent("ARCHAEOLOGY_TOGGLE");
  279. self:RegisterEvent("ARCHAEOLOGY_SURVEY_CAST");
  280. -- Events for transmogrify
  281. self:RegisterEvent("TRANSMOGRIFY_OPEN");
  282. self:RegisterEvent("TRANSMOGRIFY_CLOSE");
  283. -- Events for Adventure Journal
  284. self:RegisterEvent("AJ_OPEN");
  285. -- Events for void storage
  286. self:RegisterEvent("VOID_STORAGE_OPEN");
  287. self:RegisterEvent("VOID_STORAGE_CLOSE");
  288. -- Events for contributions
  289. self:RegisterEvent("CONTRIBUTION_COLLECTOR_OPEN");
  290. self:RegisterEvent("CONTRIBUTION_COLLECTOR_CLOSE");
  291. -- Events for Trial caps
  292. self:RegisterEvent("TRIAL_CAP_REACHED_MONEY");
  293. self:RegisterEvent("TRIAL_CAP_REACHED_LEVEL");
  294. -- Events for black market
  295. self:RegisterEvent("BLACK_MARKET_OPEN");
  296. self:RegisterEvent("BLACK_MARKET_CLOSE");
  297. -- Events for item upgrades
  298. self:RegisterEvent("ITEM_UPGRADE_MASTER_OPENED");
  299. self:RegisterEvent("ITEM_UPGRADE_MASTER_CLOSED");
  300. -- Events for Toy Box
  301. self:RegisterEvent("TOYS_UPDATED");
  302. -- Events for Heirlooms Journal
  303. self:RegisterEvent("HEIRLOOM_UPGRADE_TARGETING_CHANGED");
  304. self:RegisterEvent("HEIRLOOMS_UPDATED");
  305. -- Events for Wardrobe
  306. self:RegisterEvent("TRANSMOG_COLLECTION_UPDATED");
  307. -- Events for Quest Choice
  308. self:RegisterEvent("QUEST_CHOICE_UPDATE");
  309. -- Lua warnings
  310. self:RegisterEvent("LUA_WARNING");
  311. -- debug menu
  312. self:RegisterEvent("DEBUG_MENU_TOGGLED");
  313. -- Reveal
  314. self:RegisterEvent("REVEAL_CAPTURE_TOGGLED");
  315. -- Garrison
  316. self:RegisterEvent("GARRISON_ARCHITECT_OPENED");
  317. self:RegisterEvent("GARRISON_ARCHITECT_CLOSED");
  318. self:RegisterEvent("GARRISON_MISSION_NPC_OPENED");
  319. self:RegisterEvent("GARRISON_MISSION_NPC_CLOSED");
  320. self:RegisterEvent("GARRISON_SHIPYARD_NPC_OPENED");
  321. self:RegisterEvent("GARRISON_SHIPYARD_NPC_CLOSED");
  322. self:RegisterEvent("SHIPMENT_CRAFTER_OPENED");
  323. self:RegisterEvent("GARRISON_MONUMENT_SHOW_UI");
  324. self:RegisterEvent("GARRISON_RECRUITMENT_NPC_OPENED");
  325. self:RegisterEvent("GARRISON_TALENT_NPC_OPENED");
  326. -- Shop (for Asia promotion)
  327. self:RegisterEvent("PRODUCT_DISTRIBUTIONS_UPDATED");
  328. self:RegisterEvent("TOKEN_AUCTION_SOLD");
  329. -- Talking Head
  330. self:RegisterEvent("TALKINGHEAD_REQUESTED");
  331. -- Challenge Mode 2.0
  332. self:RegisterEvent("CHALLENGE_MODE_KEYSTONE_RECEPTABLE_OPEN");
  333. self:RegisterEvent("CHALLENGE_MODE_COMPLETED");
  334. -- Used for Order Hall UI
  335. self:RegisterUnitEvent("UNIT_AURA", "player");
  336. self:RegisterEvent("TAXIMAP_OPENED");
  337. -- Used to determine when to load BoostTutorial
  338. self:RegisterEvent("SCENARIO_UPDATE");
  339. -- Invite confirmations
  340. self:RegisterEvent("GROUP_INVITE_CONFIRMATION");
  341. self:RegisterEvent("INVITE_TO_PARTY_CONFIRMATION");
  342. -- Event(s) for the ArtifactUI
  343. self:RegisterEvent("ARTIFACT_ENDGAME_REFUND");
  344. -- Event(s) for PVP
  345. self:RegisterEvent("UPDATE_BATTLEFIELD_STATUS");
  346. self:RegisterEvent("PVP_BRAWL_INFO_UPDATED");
  347. -- Event(s) for Allied Races
  348. self:RegisterEvent("ALLIED_RACE_OPEN");
  349. -- Event(s) for Islands
  350. self:RegisterEvent("ISLAND_COMPLETED");
  351. self:RegisterEvent("ISLANDS_QUEUE_OPEN");
  352. -- Event(s) for Warfronts
  353. self:RegisterEvent("WARFRONT_COMPLETED");
  354. -- Event(s) for Azerite Empowered Items
  355. self:RegisterEvent("RESPEC_AZERITE_EMPOWERED_ITEM_OPENED");
  356. -- Event(s) for Heart of Azeroth forge
  357. self:RegisterEvent("AZERITE_ESSENCE_FORGE_OPEN");
  358. -- Events for Reporting SYSTEM
  359. self:RegisterEvent("REPORT_PLAYER_RESULT");
  360. -- Events for Global Mouse Down
  361. self:RegisterEvent("GLOBAL_MOUSE_DOWN");
  362. self:RegisterEvent("GLOBAL_MOUSE_UP");
  363. -- Event(s) for Item Interaction
  364. self:RegisterEvent("ITEM_INTERACTION_OPEN");
  365. end
  366. function UIParent_OnShow(self)
  367. if ( self.firstTimeLoaded ~= 1 ) then
  368. CloseAllWindows();
  369. self.firstTimeLoaded = nil;
  370. end
  371. if ( LowHealthFrame ) then
  372. LowHealthFrame:EvaluateVisibleState();
  373. end
  374. end
  375. function UIParent_OnHide(self)
  376. if ( LowHealthFrame ) then
  377. LowHealthFrame:EvaluateVisibleState();
  378. end
  379. end
  380. -- Addons --
  381. local FailedAddOnLoad = {};
  382. function UIParentLoadAddOn(name)
  383. local loaded, reason = LoadAddOn(name);
  384. if ( not loaded ) then
  385. if ( not FailedAddOnLoad[name] ) then
  386. message(format(ADDON_LOAD_FAILED, name, _G["ADDON_"..reason]));
  387. FailedAddOnLoad[name] = true;
  388. end
  389. end
  390. return loaded;
  391. end
  392. function ItemInteraction_LoadUI()
  393. UIParentLoadAddOn("Blizzard_ItemInteractionUI");
  394. end
  395. function IslandsQueue_LoadUI()
  396. UIParentLoadAddOn("Blizzard_IslandsQueueUI");
  397. end
  398. function PartyPose_LoadUI()
  399. UIParentLoadAddOn("Blizzard_PartyPoseUI");
  400. end
  401. function IslandsPartyPose_LoadUI()
  402. UIParentLoadAddOn("Blizzard_IslandsPartyPoseUI");
  403. end
  404. function WarfrontsPartyPose_LoadUI()
  405. UIParentLoadAddOn("Blizzard_WarfrontsPartyPoseUI");
  406. end
  407. function AlliedRaces_LoadUI()
  408. UIParentLoadAddOn("Blizzard_AlliedRacesUI");
  409. end
  410. function AuctionHouseFrame_LoadUI()
  411. UIParentLoadAddOn("Blizzard_AuctionHouseUI");
  412. end
  413. function BattlefieldMap_LoadUI()
  414. UIParentLoadAddOn("Blizzard_BattlefieldMap");
  415. end
  416. function ClassTrainerFrame_LoadUI()
  417. UIParentLoadAddOn("Blizzard_TrainerUI");
  418. end
  419. function CombatLog_LoadUI()
  420. UIParentLoadAddOn("Blizzard_CombatLog");
  421. end
  422. function Commentator_LoadUI()
  423. UIParentLoadAddOn("Blizzard_Commentator");
  424. end
  425. function GuildBankFrame_LoadUI()
  426. UIParentLoadAddOn("Blizzard_GuildBankUI");
  427. end
  428. function InspectFrame_LoadUI()
  429. UIParentLoadAddOn("Blizzard_InspectUI");
  430. end
  431. function KeyBindingFrame_LoadUI()
  432. UIParentLoadAddOn("Blizzard_BindingUI");
  433. end
  434. function MacroFrame_LoadUI()
  435. UIParentLoadAddOn("Blizzard_MacroUI");
  436. end
  437. function MacroFrame_SaveMacro()
  438. -- this will be overwritten with the real thing when the addon is loaded
  439. end
  440. function RaidFrame_LoadUI()
  441. UIParentLoadAddOn("Blizzard_RaidUI");
  442. end
  443. function SocialFrame_LoadUI()
  444. AchievementFrame_LoadUI();
  445. UIParentLoadAddOn("Blizzard_SocialUI");
  446. end
  447. function TalentFrame_LoadUI()
  448. UIParentLoadAddOn("Blizzard_TalentUI");
  449. end
  450. function TradeSkillFrame_LoadUI()
  451. UIParentLoadAddOn("Blizzard_TradeSkillUI");
  452. end
  453. function ObliterumForgeFrame_LoadUI()
  454. UIParentLoadAddOn("Blizzard_ObliterumUI");
  455. end
  456. function ScrappingMachineFrame_LoadUI()
  457. UIParentLoadAddOn("Blizzard_ScrappingMachineUI");
  458. end
  459. function GMSurveyFrame_LoadUI()
  460. UIParentLoadAddOn("Blizzard_GMSurveyUI");
  461. end
  462. function ItemSocketingFrame_LoadUI()
  463. UIParentLoadAddOn("Blizzard_ItemSocketingUI");
  464. end
  465. function ArtifactFrame_LoadUI()
  466. UIParentLoadAddOn("Blizzard_ArtifactUI");
  467. end
  468. function AdventureMapFrame_LoadUI()
  469. UIParentLoadAddOn("Blizzard_AdventureMap");
  470. end
  471. function BarberShopFrame_LoadUI()
  472. UIParentLoadAddOn("Blizzard_BarberShopUI");
  473. end
  474. function AchievementFrame_LoadUI()
  475. UIParentLoadAddOn("Blizzard_AchievementUI");
  476. end
  477. function TimeManager_LoadUI()
  478. UIParentLoadAddOn("Blizzard_TimeManager");
  479. end
  480. function TokenFrame_LoadUI()
  481. UIParentLoadAddOn("Blizzard_TokenUI");
  482. end
  483. function Calendar_LoadUI()
  484. UIParentLoadAddOn("Blizzard_Calendar");
  485. end
  486. function VoidStorage_LoadUI()
  487. UIParentLoadAddOn("Blizzard_VoidStorageUI");
  488. end
  489. function ArchaeologyFrame_LoadUI()
  490. UIParentLoadAddOn("Blizzard_ArchaeologyUI");
  491. end
  492. function GMChatFrame_LoadUI(...)
  493. if ( IsAddOnLoaded("Blizzard_GMChatUI") ) then
  494. return;
  495. else
  496. UIParentLoadAddOn("Blizzard_GMChatUI");
  497. if ( select(1, ...) ) then
  498. GMChatFrame_OnEvent(GMChatFrame, ...);
  499. end
  500. end
  501. end
  502. function Arena_LoadUI()
  503. UIParentLoadAddOn("Blizzard_ArenaUI");
  504. end
  505. function GuildFrame_LoadUI()
  506. UIParentLoadAddOn("Blizzard_GuildUI");
  507. end
  508. function LookingForGuildFrame_LoadUI()
  509. UIParentLoadAddOn("Blizzard_LookingForGuildUI");
  510. end
  511. function EncounterJournal_LoadUI()
  512. UIParentLoadAddOn("Blizzard_EncounterJournal");
  513. end
  514. function CollectionsJournal_LoadUI()
  515. UIParentLoadAddOn("Blizzard_Collections");
  516. end
  517. function BlackMarket_LoadUI()
  518. UIParentLoadAddOn("Blizzard_BlackMarketUI");
  519. end
  520. function ItemUpgrade_LoadUI()
  521. UIParentLoadAddOn("Blizzard_ItemUpgradeUI");
  522. end
  523. function QuestChoice_LoadUI()
  524. UIParentLoadAddOn("Blizzard_QuestChoice");
  525. end
  526. function WarboardQuestChoice_LoadUI()
  527. UIParentLoadAddOn("Blizzard_WarboardUI");
  528. end
  529. function Store_LoadUI()
  530. UIParentLoadAddOn("Blizzard_StoreUI");
  531. end
  532. function Garrison_LoadUI()
  533. UIParentLoadAddOn("Blizzard_GarrisonUI");
  534. end
  535. function OrderHall_LoadUI()
  536. UIParentLoadAddOn("Blizzard_OrderHallUI");
  537. end
  538. function TalkingHead_LoadUI()
  539. UIParentLoadAddOn("Blizzard_TalkingHeadUI");
  540. end
  541. function ChallengeMode_LoadUI()
  542. UIParentLoadAddOn("Blizzard_ChallengesUI");
  543. end
  544. function FlightMap_LoadUI()
  545. UIParentLoadAddOn("Blizzard_FlightMap");
  546. end
  547. function APIDocumentation_LoadUI()
  548. UIParentLoadAddOn("Blizzard_APIDocumentation");
  549. end
  550. --[[
  551. function MovePad_LoadUI()
  552. UIParentLoadAddOn("Blizzard_MovePad");
  553. end
  554. ]]
  555. function Tutorial_LoadUI()
  556. if ( GetTutorialsEnabled() and UnitLevel("player") < NPE_TUTORIAL_COMPLETE_LEVEL ) then
  557. UIParentLoadAddOn("Blizzard_Tutorial");
  558. end
  559. end
  560. function BoostTutorial_AttemptLoad()
  561. if IsBoostTutorialScenario() and not IsAddOnLoaded("Blizzard_BoostTutorial") then
  562. UIParentLoadAddOn("Blizzard_BoostTutorial");
  563. end
  564. end
  565. function ClassTrial_AttemptLoad()
  566. if C_ClassTrial.IsClassTrialCharacter() and not IsAddOnLoaded("Blizzard_ClassTrial") then
  567. UIParentLoadAddOn("Blizzard_ClassTrial");
  568. end
  569. end
  570. function ClassTrial_IsExpansionTrialUpgradeDialogShowing()
  571. return ExpansionTrialThanksForPlayingDialog and ExpansionTrialThanksForPlayingDialog:IsShowingExpansionTrialUpgrade();
  572. end
  573. function DeathRecap_LoadUI()
  574. UIParentLoadAddOn("Blizzard_DeathRecap");
  575. end
  576. function Communities_LoadUI()
  577. UIParentLoadAddOn("Blizzard_Communities");
  578. end
  579. function AzeriteRespecFrame_LoadUI()
  580. UIParentLoadAddOn("Blizzard_AzeriteRespecUI");
  581. end
  582. local playerEnteredWorld = false;
  583. local varsLoaded = false;
  584. function NPETutorial_AttemptToBegin(event)
  585. if ( NewPlayerExperience and not NewPlayerExperience.IsActive ) then
  586. NewPlayerExperience:Begin();
  587. return;
  588. end
  589. if( event == "PLAYER_ENTERING_WORLD" ) then
  590. playerEnteredWorld = true;
  591. elseif ( event == "VARIABLES_LOADED" ) then
  592. varsLoaded = true;
  593. end
  594. if ( playerEnteredWorld and varsLoaded ) then
  595. Tutorial_LoadUI();
  596. end
  597. end
  598. function OrderHall_CheckCommandBar()
  599. if (not OrderHallCommandBar or not OrderHallCommandBar:IsShown()) then
  600. if (C_Garrison.IsPlayerInGarrison(LE_GARRISON_TYPE_7_0)) then
  601. OrderHall_LoadUI();
  602. OrderHallCommandBar:Show();
  603. end
  604. end
  605. end
  606. function ShowMacroFrame()
  607. MacroFrame_LoadUI();
  608. if ( MacroFrame_Show ) then
  609. MacroFrame_Show();
  610. end
  611. end
  612. function InspectAchievements (unit)
  613. if (IsKioskModeEnabled()) then
  614. return;
  615. end
  616. AchievementFrame_LoadUI();
  617. AchievementFrame_DisplayComparison(unit);
  618. end
  619. function ToggleAchievementFrame(stats)
  620. if (IsKioskModeEnabled()) then
  621. return;
  622. end
  623. if ( ( HasCompletedAnyAchievement() or IsInGuild() ) and CanShowAchievementUI() ) then
  624. AchievementFrame_LoadUI();
  625. AchievementFrame_ToggleAchievementFrame(stats);
  626. end
  627. end
  628. function ToggleTalentFrame(suggestedTab)
  629. if (UnitLevel("player") < SHOW_SPEC_LEVEL) then
  630. return;
  631. end
  632. TalentFrame_LoadUI();
  633. if ( PlayerTalentFrame_Toggle ) then
  634. PlayerTalentFrame_Toggle(suggestedTab);
  635. end
  636. end
  637. function ToggleBattlefieldMap()
  638. BattlefieldMap_LoadUI();
  639. if ( BattlefieldMapFrame ) then
  640. BattlefieldMapFrame:Toggle();
  641. end
  642. end
  643. function ToggleTimeManager()
  644. TimeManager_LoadUI();
  645. if ( TimeManager_Toggle ) then
  646. TimeManager_Toggle();
  647. end
  648. end
  649. function ToggleCalendar()
  650. if (IsKioskModeEnabled()) then
  651. return;
  652. end
  653. Calendar_LoadUI();
  654. if ( Calendar_Toggle ) then
  655. Calendar_Toggle();
  656. end
  657. end
  658. function IsCommunitiesUIDisabledByTrialAccount()
  659. return IsTrialAccount();
  660. end
  661. function ToggleGuildFrame()
  662. if (IsKioskModeEnabled()) then
  663. return;
  664. end
  665. local factionGroup = UnitFactionGroup("player");
  666. if (factionGroup == "Neutral") then
  667. return;
  668. end
  669. if ( IsCommunitiesUIDisabledByTrialAccount() ) then
  670. UIErrorsFrame:AddMessage(ERR_RESTRICTED_ACCOUNT_TRIAL, 1.0, 0.1, 0.1, 1.0);
  671. return;
  672. elseif ( CommunitiesFrame_IsEnabled() ) then
  673. if ( not BNConnected() ) then
  674. UIErrorsFrame:AddMessage(ERR_GUILD_AND_COMMUNITIES_UNAVAILABLE, 1.0, 0.1, 0.1, 1.0);
  675. return;
  676. elseif ( C_Club.IsRestricted() ~= Enum.ClubRestrictionReason.None ) then
  677. return;
  678. end
  679. ToggleCommunitiesFrame();
  680. elseif ( IsInGuild() ) then
  681. GuildFrame_LoadUI();
  682. if ( GuildFrame_Toggle ) then
  683. GuildFrame_Toggle();
  684. end
  685. else
  686. ToggleGuildFinder();
  687. end
  688. end
  689. local function ToggleClubFinderBasedOnType(isGuildType)
  690. ToggleCommunitiesFrame();
  691. local communitiesFrame = CommunitiesFrame;
  692. if( not communitiesFrame:IsShown()) then
  693. return;
  694. end
  695. if (isGuildType) then
  696. communitiesFrame:SetDisplayMode(COMMUNITIES_FRAME_DISPLAY_MODES.GUILD_FINDER);
  697. else
  698. communitiesFrame:SetDisplayMode(COMMUNITIES_FRAME_DISPLAY_MODES.COMMUNITY_FINDER);
  699. end
  700. communitiesFrame.GuildFinderFrame.isGuildType = isGuildType;
  701. communitiesFrame.GuildFinderFrame.selectedTab = 1;
  702. communitiesFrame.GuildFinderFrame:UpdateType();
  703. communitiesFrame:SelectClub(nil);
  704. communitiesFrame.Inset:Hide();
  705. end
  706. function ToggleGuildFinder()
  707. if (IsKioskModeEnabled()) then
  708. return;
  709. end
  710. local factionGroup = UnitFactionGroup("player");
  711. if (factionGroup == "Neutral") then
  712. return;
  713. end
  714. ToggleClubFinderBasedOnType(true);
  715. end
  716. function ToggleCommunityFinder()
  717. if (IsKioskModeEnabled()) then
  718. return;
  719. end
  720. local factionGroup = UnitFactionGroup("player");
  721. if (factionGroup == "Neutral") then
  722. return;
  723. end
  724. ToggleClubFinderBasedOnType(false);
  725. end
  726. function ToggleLFDParentFrame()
  727. if (IsKioskModeEnabled()) then
  728. return;
  729. end
  730. local factionGroup = UnitFactionGroup("player");
  731. if (factionGroup == "Neutral") then
  732. return;
  733. end
  734. if ( UnitLevel("player") >= math.min(SHOW_LFD_LEVEL,SHOW_PVP_LEVEL) ) then
  735. PVEFrame_ToggleFrame("GroupFinderFrame", LFDParentFrame);
  736. end
  737. end
  738. function ToggleHelpFrame()
  739. if (IsKioskModeEnabled()) then
  740. return;
  741. end
  742. if ( HelpFrame:IsShown() ) then
  743. HideUIPanel(HelpFrame);
  744. else
  745. StaticPopup_Hide("HELP_TICKET");
  746. StaticPopup_Hide("HELP_TICKET_ABANDON_CONFIRM");
  747. StaticPopup_Hide("GM_RESPONSE_NEED_MORE_HELP");
  748. StaticPopup_Hide("GM_RESPONSE_RESOLVE_CONFIRM");
  749. StaticPopup_Hide("GM_RESPONSE_MUST_RESOLVE_RESPONSE");
  750. HelpFrame_ShowFrame();
  751. end
  752. end
  753. function ToggleRaidFrame()
  754. if (IsKioskModeEnabled()) then
  755. return;
  756. end
  757. local factionGroup = UnitFactionGroup("player");
  758. if (factionGroup == "Neutral") then
  759. return;
  760. end
  761. ToggleFriendsFrame(FRIEND_TAB_RAID);
  762. end
  763. function ToggleRaidBrowser()
  764. if (IsKioskModeEnabled()) then
  765. return;
  766. end
  767. local factionGroup = UnitFactionGroup("player");
  768. if (factionGroup == "Neutral") then
  769. return;
  770. end
  771. if ( RaidBrowserFrame:IsShown() ) then
  772. HideUIPanel(RaidBrowserFrame);
  773. else
  774. ShowUIPanel(RaidBrowserFrame);
  775. end
  776. end
  777. function CanShowEncounterJournal()
  778. if ( not C_AdventureJournal.CanBeShown() ) then
  779. return false;
  780. end
  781. return true;
  782. end
  783. function ToggleEncounterJournal()
  784. if ( not CanShowEncounterJournal() ) then
  785. return false;
  786. end
  787. if ( not EncounterJournal ) then
  788. EncounterJournal_LoadUI();
  789. end
  790. if ( EncounterJournal ) then
  791. ToggleFrame(EncounterJournal);
  792. return true;
  793. end
  794. return false;
  795. end
  796. function ToggleCommunitiesFrame()
  797. Communities_LoadUI();
  798. ToggleFrame(CommunitiesFrame);
  799. end
  800. function CommunitiesFrame_IsEnabled()
  801. return C_Club.IsEnabled();
  802. end
  803. COLLECTIONS_JOURNAL_TAB_INDEX_MOUNTS = 1;
  804. COLLECTIONS_JOURNAL_TAB_INDEX_PETS = COLLECTIONS_JOURNAL_TAB_INDEX_MOUNTS + 1;
  805. COLLECTIONS_JOURNAL_TAB_INDEX_TOYS = COLLECTIONS_JOURNAL_TAB_INDEX_PETS + 1;
  806. COLLECTIONS_JOURNAL_TAB_INDEX_HEIRLOOMS = COLLECTIONS_JOURNAL_TAB_INDEX_TOYS + 1;
  807. COLLECTIONS_JOURNAL_TAB_INDEX_APPEARANCES = COLLECTIONS_JOURNAL_TAB_INDEX_HEIRLOOMS + 1;
  808. function ToggleCollectionsJournal(tabIndex)
  809. if CollectionsJournal then
  810. local tabMatches = not tabIndex or tabIndex == PanelTemplates_GetSelectedTab(CollectionsJournal);
  811. local isShown = CollectionsJournal:IsShown() and tabMatches;
  812. SetCollectionsJournalShown(not isShown, tabIndex);
  813. else
  814. SetCollectionsJournalShown(true, tabIndex);
  815. end
  816. end
  817. function SetCollectionsJournalShown(shown, tabIndex)
  818. if not CollectionsJournal then
  819. CollectionsJournal_LoadUI();
  820. end
  821. if CollectionsJournal then
  822. if shown then
  823. ShowUIPanel(CollectionsJournal);
  824. if tabIndex then
  825. CollectionsJournal_SetTab(CollectionsJournal, tabIndex);
  826. end
  827. else
  828. HideUIPanel(CollectionsJournal);
  829. end
  830. end
  831. end
  832. function ToggleToyCollection(autoPageToCollectedToyID)
  833. CollectionsJournal_LoadUI();
  834. ToyBox.autoPageToCollectedToyID = autoPageToCollectedToyID;
  835. SetCollectionsJournalShown(true, COLLECTIONS_JOURNAL_TAB_INDEX_TOYS);
  836. end
  837. function TogglePVPUI()
  838. if (IsKioskModeEnabled()) then
  839. return;
  840. end
  841. if ( UnitLevel("player") >= math.min(SHOW_LFD_LEVEL,SHOW_PVP_LEVEL) ) then
  842. PVEFrame_ToggleFrame("PVPUIFrame", nil);
  843. end
  844. end
  845. function ToggleStoreUI()
  846. if (IsKioskModeEnabled()) then
  847. return;
  848. end
  849. Store_LoadUI();
  850. local wasShown = StoreFrame_IsShown();
  851. if ( not wasShown ) then
  852. --We weren't showing, now we are. We should hide all other panels.
  853. securecall("CloseAllWindows");
  854. end
  855. StoreFrame_SetShown(not wasShown);
  856. end
  857. function SetStoreUIShown(shown)
  858. if (IsKioskModeEnabled()) then
  859. return;
  860. end
  861. Store_LoadUI();
  862. local wasShown = StoreFrame_IsShown();
  863. if ( not wasShown and shown ) then
  864. --We weren't showing, now we are. We should hide all other panels.
  865. securecall("CloseAllWindows");
  866. end
  867. StoreFrame_SetShown(shown);
  868. end
  869. function ToggleGarrisonBuildingUI()
  870. if (not GarrisonBuildingFrame) then
  871. Garrison_LoadUI();
  872. end
  873. GarrisonBuildingUI_ToggleFrame();
  874. end
  875. function ToggleGarrisonMissionUI()
  876. if (not GarrisonMissionFrame) then
  877. Garrison_LoadUI();
  878. end
  879. GarrisonMissionFrame_ToggleFrame();
  880. end
  881. function ToggleOrderHallTalentUI()
  882. if (not OrderHallTalentFrame) then
  883. OrderHall_LoadUI();
  884. end
  885. OrderHallTalentFrame_ToggleFrame();
  886. end
  887. function OpenDeathRecapUI(id)
  888. if (not DeathRecapFrame) then
  889. DeathRecap_LoadUI();
  890. end
  891. DeathRecapFrame_OpenRecap(id);
  892. end
  893. function InspectUnit(unit)
  894. InspectFrame_LoadUI();
  895. if ( InspectFrame_Show ) then
  896. InspectFrame_Show(unit);
  897. end
  898. end
  899. function OpenAzeriteEmpoweredItemUIFromItemLocation(itemLocation)
  900. UIParentLoadAddOn("Blizzard_AzeriteUI");
  901. ShowUIPanel(AzeriteEmpoweredItemUI);
  902. if AzeriteEmpoweredItemUI:IsShown() then -- may fail to display
  903. AzeriteEmpoweredItemUI:SetToItemAtLocation(itemLocation);
  904. end
  905. end
  906. function OpenAzeriteEmpoweredItemUIFromLink(itemLink, overrideClassID, overrideSelectedPowersList)
  907. UIParentLoadAddOn("Blizzard_AzeriteUI");
  908. ShowUIPanel(AzeriteEmpoweredItemUI);
  909. if AzeriteEmpoweredItemUI:IsShown() then -- may fail to display
  910. AzeriteEmpoweredItemUI:SetToItemLink(itemLink, overrideClassID, overrideSelectedPowersList);
  911. end
  912. end
  913. function OpenAzeriteEssenceUIFromItemLocation(itemLocation)
  914. UIParentLoadAddOn("Blizzard_AzeriteEssenceUI");
  915. if AzeriteEssenceUI then
  916. AzeriteEssenceUI:TryShow();
  917. end
  918. end
  919. local function PlayBattlefieldBanner(self)
  920. -- battlefields
  921. if ( not self.battlefieldBannerShown ) then
  922. local bannerName, bannerDescription;
  923. if (C_PvP.IsInBrawl()) then
  924. local brawlInfo = C_PvP.GetActiveBrawlInfo();
  925. if (brawlInfo) then
  926. bannerName = brawlInfo.name;
  927. bannerDescription = brawlInfo.shortDescription;
  928. end
  929. else
  930. for i=1, GetMaxBattlefieldID() do
  931. local status, mapName, _, _, _, _, _, _, _, shortDescription, _ = GetBattlefieldStatus(i);
  932. if ( status and status == "active" ) then
  933. bannerName = mapName;
  934. bannerDescription = shortDescription;
  935. break;
  936. end
  937. end
  938. end
  939. if ( bannerName ) then
  940. UIParentLoadAddOn("Blizzard_PVPUI");
  941. C_Timer.After(1, function() TopBannerManager_Show(PvPObjectiveBannerFrame, { name=bannerName, description=bannerDescription }); end);
  942. self.battlefieldBannerShown = true;
  943. end
  944. end
  945. end
  946. local function HandlesGlobalMouseEvent(focus, buttonID, event)
  947. return focus and focus.HandlesGlobalMouseEvent and focus:HandlesGlobalMouseEvent(buttonID, event);
  948. end
  949. local function HasVisibleAutoCompleteBox(autoCompleteBoxList, mouseFocus)
  950. for i, box in ipairs(autoCompleteBoxList) do
  951. if box:IsShown() and DoesAncestryInclude(box, mouseFocus) then
  952. return true;
  953. end
  954. end
  955. return false;
  956. end
  957. -- UIParent_OnEvent --
  958. function UIParent_OnEvent(self, event, ...)
  959. local arg1, arg2, arg3, arg4, arg5, arg6 = ...;
  960. if ( event == "CURRENT_SPELL_CAST_CHANGED" ) then
  961. if ( SpellCanTargetGarrisonFollower(0) or SpellCanTargetGarrisonFollowerAbility(0, 0) ) then
  962. local followerTypeID = GetFollowerTypeIDFromSpell();
  963. local frame = _G[GarrisonFollowerOptions[followerTypeID].missionFrame];
  964. if (frame and frame:IsShown()) then
  965. if ( (not C_Garrison.TargetSpellHasFollowerTemporaryAbility() or not frame:HasMission()) and PanelTemplates_GetSelectedTab(frame) ~= 2 ) then
  966. frame:SelectTab(2)
  967. end
  968. else
  969. local landingPageTabIndex;
  970. local garrTypeID = GarrisonFollowerOptions[followerTypeID].garrisonType;
  971. if (C_Garrison.HasGarrison(garrTypeID)) then
  972. if (followerTypeID == LE_FOLLOWER_TYPE_SHIPYARD_6_2) then
  973. landingPageTabIndex = 3;
  974. else
  975. landingPageTabIndex = 2;
  976. end
  977. ShowGarrisonLandingPage(garrTypeID);
  978. -- switch to the followers tab
  979. if ( PanelTemplates_GetSelectedTab(GarrisonLandingPage) ~= landingPageTabIndex ) then
  980. GarrisonLandingPageTab_SetTab(_G["GarrisonLandingPageTab"..landingPageTabIndex]);
  981. end
  982. end
  983. end
  984. end
  985. if ( SpellCanTargetGarrisonMission() ) then
  986. -- TODO: Determine garrison/follower mission type for this spell
  987. if ( not GarrisonLandingPage ) then
  988. Garrison_LoadUI();
  989. end
  990. -- if the mission UI is already open, go with that
  991. if ( GarrisonMissionFrame:IsShown() ) then
  992. if ( PanelTemplates_GetSelectedTab(GarrisonMissionFrame) ~= 1 ) then
  993. GarrisonMissionFrame_SelectTab(1);
  994. end
  995. if ( PanelTemplates_GetSelectedTab(GarrisonMissionFrame.MissionTab.MissionList) ~= 2 ) then
  996. GarrisonMissionListTab_SetTab(GarrisonMissionFrame.MissionTab.MissionList.Tab2);
  997. end
  998. else
  999. if (C_Garrison.HasGarrison(LE_GARRISON_TYPE_6_0)) then
  1000. ShowGarrisonLandingPage(LE_GARRISON_TYPE_6_0);
  1001. -- switch to the mission tab
  1002. if ( PanelTemplates_GetSelectedTab(GarrisonLandingPage) ~= 1 ) then
  1003. GarrisonLandingPageTab_SetTab(GarrisonLandingPageTab1);
  1004. end
  1005. if ( PanelTemplates_GetSelectedTab(GarrisonLandingPageReport) ~= GarrisonLandingPageReport.InProgress ) then
  1006. GarrisonLandingPageReport_SetTab(GarrisonLandingPageReport.InProgress);
  1007. end
  1008. end
  1009. end
  1010. end
  1011. if ( #StaticPopup_DisplayedFrames > 0 ) then
  1012. if ( arg1 ) then
  1013. StaticPopup_Hide("BIND_ENCHANT");
  1014. StaticPopup_Hide("REPLACE_ENCHANT");
  1015. StaticPopup_Hide("ACTION_WILL_BIND_ITEM");
  1016. end
  1017. StaticPopup_Hide("TRADE_REPLACE_ENCHANT");
  1018. StaticPopup_Hide("END_BOUND_TRADEABLE");
  1019. if ( not SpellCanTargetGarrisonFollower(0) ) then
  1020. StaticPopup_Hide("CONFIRM_FOLLOWER_UPGRADE");
  1021. StaticPopup_Hide("CONFIRM_FOLLOWER_TEMPORARY_ABILITY");
  1022. end
  1023. end
  1024. elseif ( event == "VARIABLES_LOADED" ) then
  1025. UIParent.variablesLoaded = true;
  1026. LocalizeFrames();
  1027. if ( not TimeManagerFrame and GetCVar("timeMgrAlarmEnabled") == "1" ) then
  1028. -- We have to load the time manager here if the alarm is enabled because the alarm can go off
  1029. -- even if the clock is not shown. WorldFrame_OnUpdate handles alarm checking while the clock
  1030. -- is hidden.
  1031. TimeManager_LoadUI();
  1032. end
  1033. if ( not BattlefieldMapFrame and GetCVar("showBattlefieldMinimap") == "1" ) then
  1034. BattlefieldMap_LoadUI();
  1035. end
  1036. local lastTalkedToGM = GetCVar("lastTalkedToGM");
  1037. if ( lastTalkedToGM ~= "" ) then
  1038. GMChatFrame_LoadUI();
  1039. GMChatFrame:Show()
  1040. local info = ChatTypeInfo["WHISPER"];
  1041. GMChatFrame:AddMessage(format(GM_CHAT_LAST_SESSION, "|TInterface\\ChatFrame\\UI-ChatIcon-Blizz:12:20:0:0:32:16:4:28:0:16|t "..
  1042. GetGMLink(lastTalkedToGM, "["..lastTalkedToGM.."]")), info.r, info.g, info.b, info.id);
  1043. GMChatFrameEditBox:SetAttribute("tellTarget", lastTalkedToGM);
  1044. GMChatFrameEditBox:SetAttribute("chatType", "WHISPER");
  1045. end
  1046. TargetFrame_OnVariablesLoaded();
  1047. NPETutorial_AttemptToBegin(event);
  1048. StoreFrame_CheckForFree(event);
  1049. elseif ( event == "PLAYER_LOGIN" ) then
  1050. TimeManager_LoadUI();
  1051. -- You can override this if you want a Combat Log replacement
  1052. CombatLog_LoadUI();
  1053. elseif ( event == "PLAYER_DEAD" ) then
  1054. if ( not StaticPopup_Visible("DEATH") ) then
  1055. CloseAllWindows(1);
  1056. end
  1057. if ( (GetReleaseTimeRemaining() > 0 or GetReleaseTimeRemaining() == -1) and (not ResurrectGetOfferer()) ) then
  1058. StaticPopup_Show("DEATH");
  1059. end
  1060. elseif ( event == "SELF_RES_SPELL_CHANGED" ) then
  1061. if ( StaticPopup_Visible("DEATH") ) then
  1062. StaticPopup_Show("DEATH"); --If we're already showing a death prompt, we should refresh it.
  1063. end
  1064. elseif ( event == "PLAYER_ALIVE" or event == "RAISED_AS_GHOUL" ) then
  1065. StaticPopup_Hide("DEATH");
  1066. StaticPopup_Hide("RESURRECT_NO_SICKNESS");
  1067. StaticPopup_Hide("RESURRECT_NO_TIMER");
  1068. StaticPopup_Hide("RESURRECT");
  1069. if ( UnitIsGhost("player") ) then
  1070. GhostFrame:Show();
  1071. else
  1072. GhostFrame:Hide();
  1073. end
  1074. elseif ( event == "PLAYER_UNGHOST" ) then
  1075. StaticPopup_Hide("RESURRECT");
  1076. StaticPopup_Hide("RESURRECT_NO_SICKNESS");
  1077. StaticPopup_Hide("RESURRECT_NO_TIMER");
  1078. StaticPopup_Hide("SKINNED");
  1079. StaticPopup_Hide("SKINNED_REPOP");
  1080. GhostFrame:Hide();
  1081. elseif ( event == "RESURRECT_REQUEST" ) then
  1082. ShowResurrectRequest(arg1);
  1083. elseif ( event == "PLAYER_SKINNED" ) then
  1084. StaticPopup_Hide("RESURRECT");
  1085. StaticPopup_Hide("RESURRECT_NO_SICKNESS");
  1086. StaticPopup_Hide("RESURRECT_NO_TIMER");
  1087. --[[
  1088. if (arg1 == 1) then
  1089. StaticPopup_Show("SKINNED_REPOP");
  1090. else
  1091. StaticPopup_Show("SKINNED");
  1092. end
  1093. ]]
  1094. UIErrorsFrame:AddMessage(DEATH_CORPSE_SKINNED, 1.0, 0.1, 0.1, 1.0);
  1095. elseif ( event == "TRADE_REQUEST" ) then
  1096. StaticPopup_Show("TRADE", arg1);
  1097. elseif ( event == "CHANNEL_INVITE_REQUEST" ) then
  1098. if ( GetCVarBool("blockChannelInvites") ) then
  1099. DeclineChannelInvite(arg1);
  1100. else
  1101. local dialog = StaticPopup_Show("CHAT_CHANNEL_INVITE", arg1, arg2);
  1102. if ( dialog ) then
  1103. dialog.data = arg1;
  1104. end
  1105. end
  1106. elseif ( event == "CHANNEL_PASSWORD_REQUEST" ) then
  1107. local dialog = StaticPopup_Show("CHAT_CHANNEL_PASSWORD", arg1);
  1108. if ( dialog ) then
  1109. dialog.data = arg1;
  1110. end
  1111. elseif ( event == "PARTY_INVITE_REQUEST" ) then
  1112. FlashClientIcon();
  1113. local name, tank, healer, damage, isXRealm, allowMultipleRoles, inviterGuid, isQuestSessionActive = ...;
  1114. -- Color the name by our relationship
  1115. local modifiedName, color, selfRelationship = SocialQueueUtil_GetRelationshipInfo(inviterGuid);
  1116. if ( selfRelationship ) then
  1117. name = color..name..FONT_COLOR_CODE_CLOSE;
  1118. end
  1119. -- if there's a role, it's an LFG invite
  1120. if ( tank or healer or damage ) then
  1121. StaticPopupSpecial_Show(LFGInvitePopup);
  1122. LFGInvitePopup_Update(name, tank, healer, damage, allowMultipleRoles, isQuestSessionActive);
  1123. else
  1124. local text = isXRealm and INVITATION_XREALM or INVITATION;
  1125. text = string.format(text, name);
  1126. if ( WillAcceptInviteRemoveQueues() ) then
  1127. text = text.."\n\n"..ACCEPTING_INVITE_WILL_REMOVE_QUEUE;
  1128. end
  1129. if isQuestSessionActive then
  1130. QuestSessionManager:ShowGroupInviteReceivedConfirmation(name, text);
  1131. else
  1132. StaticPopup_Show("PARTY_INVITE", text);
  1133. end
  1134. end
  1135. elseif ( event == "PARTY_INVITE_CANCEL" ) then
  1136. StaticPopup_Hide("PARTY_INVITE");
  1137. StaticPopupSpecial_Hide(LFGInvitePopup);
  1138. elseif ( event == "GUILD_INVITE_REQUEST" ) then
  1139. StaticPopup_Show("GUILD_INVITE", arg1, arg2);
  1140. elseif ( event == "GUILD_INVITE_CANCEL" ) then
  1141. StaticPopup_Hide("GUILD_INVITE");
  1142. elseif ( event == "PLAYER_CAMPING" ) then
  1143. StaticPopup_Show("CAMP");
  1144. elseif ( event == "PLAYER_QUITING" ) then
  1145. StaticPopup_Show("QUIT");
  1146. elseif ( event == "LOGOUT_CANCEL" ) then
  1147. StaticPopup_Hide("CAMP");
  1148. StaticPopup_Hide("QUIT");
  1149. elseif ( event == "LOOT_BIND_CONFIRM" ) then
  1150. local texture, item, quantity, currencyID, quality, locked = GetLootSlotInfo(arg1);
  1151. local dialog = StaticPopup_Show("LOOT_BIND", ITEM_QUALITY_COLORS[quality].hex..item.."|r");
  1152. if ( dialog ) then
  1153. dialog.data = arg1;
  1154. end
  1155. elseif ( event == "EQUIP_BIND_CONFIRM" ) then
  1156. StaticPopup_Hide("EQUIP_BIND_TRADEABLE");
  1157. local dialog = StaticPopup_Show("EQUIP_BIND");
  1158. if ( dialog ) then
  1159. dialog.data = arg1;
  1160. end
  1161. elseif ( event == "EQUIP_BIND_TRADEABLE_CONFIRM" ) then
  1162. StaticPopup_Hide("EQUIP_BIND");
  1163. local dialog = StaticPopup_Show("EQUIP_BIND_TRADEABLE");
  1164. if ( dialog ) then
  1165. dialog.data = arg1;
  1166. end
  1167. elseif ( event == "USE_BIND_CONFIRM" ) then
  1168. StaticPopup_Show("USE_BIND");
  1169. elseif( event == "USE_NO_REFUND_CONFIRM" )then
  1170. StaticPopup_Show("USE_NO_REFUND_CONFIRM");
  1171. elseif ( event == "CONFIRM_BEFORE_USE" ) then
  1172. StaticPopup_Show("CONFIM_BEFORE_USE");
  1173. elseif ( event == "DELETE_ITEM_CONFIRM" ) then
  1174. -- Check quality, ignore heirlooms
  1175. if ( arg2 >= LE_ITEM_QUALITY_RARE and arg2 ~= LE_ITEM_QUALITY_HEIRLOOM ) then
  1176. if (arg4 == 1) then -- quest item?
  1177. StaticPopup_Show("DELETE_GOOD_QUEST_ITEM", arg1);
  1178. else
  1179. StaticPopup_Show("DELETE_GOOD_ITEM", arg1);
  1180. end
  1181. else
  1182. if (arg4 == 1) then -- quest item?
  1183. StaticPopup_Show("DELETE_QUEST_ITEM", arg1);
  1184. else
  1185. StaticPopup_Show("DELETE_ITEM", arg1);
  1186. end
  1187. end
  1188. elseif ( event == "QUEST_ACCEPT_CONFIRM" ) then
  1189. local numEntries, numQuests = GetNumQuestLogEntries();
  1190. if( numQuests >= MAX_QUESTS) then
  1191. StaticPopup_Show("QUEST_ACCEPT_LOG_FULL", arg1, arg2);
  1192. else
  1193. StaticPopup_Show("QUEST_ACCEPT", arg1, arg2);
  1194. end
  1195. elseif ( event =="QUEST_LOG_UPDATE" or event == "UNIT_QUEST_LOG_CHANGED" ) then
  1196. local frameName = StaticPopup_Visible("QUEST_ACCEPT_LOG_FULL");
  1197. if( frameName ) then
  1198. local numEntries, numQuests = GetNumQuestLogEntries();
  1199. local button = _G[frameName.."Button1"];
  1200. if( numQuests < MAX_QUESTS ) then
  1201. button:Enable();
  1202. else
  1203. button:Disable();
  1204. end
  1205. end
  1206. elseif ( event == "CURSOR_UPDATE" ) then
  1207. if ( not CursorHasItem() ) then
  1208. StaticPopup_Hide("EQUIP_BIND");
  1209. StaticPopup_Hide("EQUIP_BIND_TRADEABLE");
  1210. end
  1211. elseif ( event == "PLAYER_ENTERING_WORLD" ) then
  1212. -- Get multi-actionbar states (before CloseAllWindows() since that may be hooked by AddOns)
  1213. -- 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.
  1214. -- SHOW_MULTI_ACTIONBAR_1, SHOW_MULTI_ACTIONBAR_2, SHOW_MULTI_ACTIONBAR_3, SHOW_MULTI_ACTIONBAR_4 = GetActionBarToggles();
  1215. MultiActionBar_Update();
  1216. -- Close any windows that were previously open
  1217. CloseAllWindows(1);
  1218. UpdateMicroButtons();
  1219. -- Fix for Bug 124392
  1220. StaticPopup_Hide("CONFIRM_LEAVE_BATTLEFIELD");
  1221. local _, instanceType = IsInInstance();
  1222. if ( instanceType == "arena" or instanceType == "pvp") then
  1223. Arena_LoadUI();
  1224. end
  1225. if ( C_Commentator.IsSpectating() ) then
  1226. Commentator_LoadUI();
  1227. end
  1228. if ( UnitIsGhost("player") ) then
  1229. GhostFrame:Show();
  1230. else
  1231. GhostFrame:Hide();
  1232. end
  1233. if ( GetReleaseTimeRemaining() > 0 or GetReleaseTimeRemaining() == -1 ) then
  1234. StaticPopup_Show("DEATH");
  1235. end
  1236. local alreadyShowingSummonPopup = StaticPopup_Visible("CONFIRM_SUMMON_STARTING_AREA") or StaticPopup_Visible("CONFIRM_SUMMON_SCENARIO") or StaticPopup_Visible("CONFIRM_SUMMON")
  1237. if ( not alreadyShowingSummonPopup and C_SummonInfo.GetSummonConfirmTimeLeft() > 0 ) then
  1238. local summonReason = C_SummonInfo.GetSummonReason();
  1239. local isSkippingStartingArea = C_SummonInfo.IsSummonSkippingStartExperience();
  1240. if ( isSkippingStartingArea ) then -- check if skiping start experience
  1241. StaticPopup_Show("CONFIRM_SUMMON_STARTING_AREA");
  1242. elseif (summonType == LE_SUMMON_REASON_SCENARIO) then
  1243. StaticPopup_Show("CONFIRM_SUMMON_SCENARIO");
  1244. else
  1245. StaticPopup_Show("CONFIRM_SUMMON");
  1246. end
  1247. end
  1248. -- display loot specialization setting
  1249. PrintLootSpecialization();
  1250. UpdateUIParentRelativeToDebugMenu();
  1251. --Bonus roll/spell confirmation.
  1252. local spellConfirmations = GetSpellConfirmationPromptsInfo();
  1253. for i, spellConfirmation in ipairs(spellConfirmations) do
  1254. if spellConfirmation.spellID then
  1255. if spellConfirmation.confirmType == LE_SPELL_CONFIRMATION_PROMPT_TYPE_STATIC_TEXT then
  1256. StaticPopup_Show("SPELL_CONFIRMATION_PROMPT", spellConfirmation.text, spellConfirmation.duration, spellConfirmation.spellID);
  1257. elseif spellConfirmation.confirmType == LE_SPELL_CONFIRMATION_PROMPT_TYPE_SIMPLE_WARNING then
  1258. StaticPopup_Show("SPELL_CONFIRMATION_WARNING", spellConfirmation.text, nil, spellConfirmation.spellID);
  1259. elseif spellConfirmation.confirmType == LE_SPELL_CONFIRMATION_PROMPT_TYPE_BONUS_ROLL then
  1260. BonusRollFrame_StartBonusRoll(spellConfirmation.spellID, spellConfirmation.text, spellConfirmation.duration, spellConfirmation.currencyID, spellConfirmation.currencyCost, spellConfirmation.difficultyID);
  1261. end
  1262. end
  1263. end
  1264. local resurrectOfferer = ResurrectGetOfferer();
  1265. if resurrectOfferer then
  1266. ShowResurrectRequest(resurrectOfferer);
  1267. end
  1268. --Group Loot Roll Windows.
  1269. local pendingLootRollIDs = GetActiveLootRollIDs();
  1270. for i=1, #pendingLootRollIDs do
  1271. GroupLootFrame_OpenNewFrame(pendingLootRollIDs[i], GetLootRollTimeLeft(pendingLootRollIDs[i]));
  1272. end
  1273. OrderHall_CheckCommandBar();
  1274. self.battlefieldBannerShown = nil;
  1275. NPETutorial_AttemptToBegin(event);
  1276. ClassTrial_AttemptLoad();
  1277. BoostTutorial_AttemptLoad();
  1278. elseif ( event == "UPDATE_BATTLEFIELD_STATUS" or event == "PVP_BRAWL_INFO_UPDATED" ) then
  1279. PlayBattlefieldBanner(self);
  1280. elseif ( event == "GROUP_ROSTER_UPDATE" ) then
  1281. -- Hide/Show party member frames
  1282. RaidOptionsFrame_UpdatePartyFrames();
  1283. if ( not IsInGroup(LE_PARTY_CATEGORY_INSTANCE) ) then
  1284. StaticPopup_Hide("CONFIRM_LEAVE_INSTANCE_PARTY");
  1285. end
  1286. elseif ( event == "MIRROR_TIMER_START" ) then
  1287. MirrorTimer_Show(arg1, arg2, arg3, arg4, arg5, arg6);
  1288. elseif ( event == "DUEL_REQUESTED" ) then
  1289. StaticPopup_Show("DUEL_REQUESTED", arg1);
  1290. elseif ( event == "DUEL_OUTOFBOUNDS" ) then
  1291. StaticPopup_Show("DUEL_OUTOFBOUNDS");
  1292. elseif ( event == "DUEL_INBOUNDS" ) then
  1293. StaticPopup_Hide("DUEL_OUTOFBOUNDS");
  1294. elseif ( event == "DUEL_FINISHED" ) then
  1295. StaticPopup_Hide("DUEL_REQUESTED");
  1296. StaticPopup_Hide("DUEL_OUTOFBOUNDS");
  1297. elseif ( event == "PET_BATTLE_PVP_DUEL_REQUESTED" ) then
  1298. StaticPopup_Show("PET_BATTLE_PVP_DUEL_REQUESTED", arg1);
  1299. elseif ( event == "PET_BATTLE_PVP_DUEL_REQUEST_CANCEL" ) then
  1300. StaticPopup_Hide("PET_BATTLE_PVP_DUEL_REQUESTED");
  1301. elseif ( event == "PET_BATTLE_QUEUE_PROPOSE_MATCH" ) then
  1302. PlaySound(SOUNDKIT.UI_PET_BATTLES_PVP_THROUGH_QUEUE);
  1303. StaticPopupSpecial_Show(PetBattleQueueReadyFrame);
  1304. elseif ( event == "PET_BATTLE_QUEUE_PROPOSAL_DECLINED" or event == "PET_BATTLE_QUEUE_PROPOSAL_ACCEPTED" ) then
  1305. StaticPopupSpecial_Hide(PetBattleQueueReadyFrame);
  1306. elseif ( event == "TRADE_REQUEST_CANCEL" ) then
  1307. StaticPopup_Hide("TRADE");
  1308. elseif ( event == "CONFIRM_XP_LOSS" ) then
  1309. local resSicknessTime = GetResSicknessDuration();
  1310. if ( resSicknessTime ) then
  1311. local dialog = nil;
  1312. if (UnitLevel("player") <= 10) then
  1313. dialog = StaticPopup_Show("XP_LOSS_NO_DURABILITY", resSicknessTime);
  1314. else
  1315. dialog = StaticPopup_Show("XP_LOSS", resSicknessTime);
  1316. end
  1317. if ( dialog ) then
  1318. dialog.data = resSicknessTime;
  1319. end
  1320. else
  1321. local dialog = nil;
  1322. if (UnitLevel("player") <= 10) then
  1323. dialog = StaticPopup_Show("XP_LOSS_NO_SICKNESS_NO_DURABILITY");
  1324. else
  1325. dialog = StaticPopup_Show("XP_LOSS_NO_SICKNESS");
  1326. end
  1327. if ( dialog ) then
  1328. dialog.data = 1;
  1329. end
  1330. end
  1331. HideUIPanel(GossipFrame);
  1332. elseif ( event == "CORPSE_IN_RANGE" ) then
  1333. StaticPopup_Show("RECOVER_CORPSE");
  1334. elseif ( event == "CORPSE_IN_INSTANCE" ) then
  1335. StaticPopup_Show("RECOVER_CORPSE_INSTANCE");
  1336. elseif ( event == "CORPSE_OUT_OF_RANGE" ) then
  1337. StaticPopup_Hide("RECOVER_CORPSE");
  1338. StaticPopup_Hide("RECOVER_CORPSE_INSTANCE");
  1339. StaticPopup_Hide("XP_LOSS");
  1340. elseif ( event == "AREA_SPIRIT_HEALER_IN_RANGE" ) then
  1341. AcceptAreaSpiritHeal();
  1342. StaticPopup_Show("AREA_SPIRIT_HEAL");
  1343. elseif ( event == "AREA_SPIRIT_HEALER_OUT_OF_RANGE" ) then
  1344. StaticPopup_Hide("AREA_SPIRIT_HEAL");
  1345. elseif (event == "ACTION_WILL_BIND_ITEM") then
  1346. StaticPopup_Show("ACTION_WILL_BIND_ITEM");
  1347. elseif ( event == "BIND_ENCHANT" ) then
  1348. StaticPopup_Show("BIND_ENCHANT");
  1349. elseif ( event == "REPLACE_ENCHANT" ) then
  1350. StaticPopup_Show("REPLACE_ENCHANT", arg1, arg2);
  1351. elseif ( event == "TRADE_REPLACE_ENCHANT" ) then
  1352. StaticPopup_Show("TRADE_REPLACE_ENCHANT", arg1, arg2);
  1353. elseif ( event == "END_BOUND_TRADEABLE" ) then
  1354. local dialog = StaticPopup_Show("END_BOUND_TRADEABLE", nil, nil, arg1);
  1355. elseif ( event == "MACRO_ACTION_BLOCKED" or event == "ADDON_ACTION_BLOCKED" ) then
  1356. DisplayInterfaceActionBlockedMessage();
  1357. elseif ( event == "MACRO_ACTION_FORBIDDEN" ) then
  1358. StaticPopup_Show("MACRO_ACTION_FORBIDDEN");
  1359. elseif ( event == "ADDON_ACTION_FORBIDDEN" ) then
  1360. local dialog = StaticPopup_Show("ADDON_ACTION_FORBIDDEN", arg1);
  1361. if ( dialog ) then
  1362. dialog.data = arg1;
  1363. end
  1364. elseif ( event == "PLAYER_CONTROL_LOST" ) then
  1365. if ( UnitOnTaxi("player") ) then
  1366. return;
  1367. end
  1368. CloseAllWindows_WithExceptions();
  1369. --[[
  1370. -- Disable all microbuttons except the main menu
  1371. SetDesaturation(MicroButtonPortrait, true);
  1372. Designers previously wanted these disabled when feared, they seem to have changed their minds
  1373. CharacterMicroButton:Disable();
  1374. SpellbookMicroButton:Disable();
  1375. TalentMicroButton:Disable();
  1376. QuestLogMicroButton:Disable();
  1377. GuildMicroButton:Disable();
  1378. WorldMapMicroButton:Disable();
  1379. ]]
  1380. UIParent.isOutOfControl = 1;
  1381. elseif ( event == "PLAYER_CONTROL_GAINED" ) then
  1382. --[[
  1383. -- Enable all microbuttons
  1384. SetDesaturation(MicroButtonPortrait, false);
  1385. CharacterMicroButton:Enable();
  1386. SpellbookMicroButton:Enable();
  1387. TalentMicroButton:Enable();
  1388. QuestLogMicroButton:Enable();
  1389. GuildMicroButton:Enable();
  1390. WorldMapMicroButton:Enable();
  1391. ]]
  1392. UIParent.isOutOfControl = nil;
  1393. elseif ( event == "START_LOOT_ROLL" ) then
  1394. GroupLootFrame_OpenNewFrame(arg1, arg2);
  1395. elseif ( event == "CONFIRM_LOOT_ROLL" ) then
  1396. local texture, name, count, quality, bindOnPickUp = GetLootRollItemInfo(arg1);
  1397. local dialog = StaticPopup_Show("CONFIRM_LOOT_ROLL", ITEM_QUALITY_COLORS[quality].hex..name.."|r");
  1398. if ( dialog ) then
  1399. dialog.text:SetFormattedText(arg3, ITEM_QUALITY_COLORS[quality].hex..name.."|r");
  1400. StaticPopup_Resize(dialog, "CONFIRM_LOOT_ROLL");
  1401. dialog.data = arg1;
  1402. dialog.data2 = arg2;
  1403. end
  1404. elseif ( event == "SPELL_CONFIRMATION_PROMPT" ) then
  1405. local spellID, confirmType, text, duration, currencyID, currencyCost, difficultyID = ...;
  1406. if ( confirmType == LE_SPELL_CONFIRMATION_PROMPT_TYPE_STATIC_TEXT ) then
  1407. StaticPopup_Show("SPELL_CONFIRMATION_PROMPT", text, duration, spellID);
  1408. elseif ( confirmType == LE_SPELL_CONFIRMATION_PROMPT_TYPE_SIMPLE_WARNING ) then
  1409. StaticPopup_Show("SPELL_CONFIRMATION_WARNING", text, nil, spellID);
  1410. elseif ( confirmType == LE_SPELL_CONFIRMATION_PROMPT_TYPE_BONUS_ROLL ) then
  1411. BonusRollFrame_StartBonusRoll(spellID, text, duration, currencyID, currencyCost, difficultyID);
  1412. end
  1413. elseif ( event == "SPELL_CONFIRMATION_TIMEOUT" ) then
  1414. local spellID, confirmType = ...;
  1415. if ( confirmType == LE_SPELL_CONFIRMATION_PROMPT_TYPE_STATIC_TEXT ) then
  1416. StaticPopup_Hide("SPELL_CONFIRMATION_PROMPT", spellID);
  1417. elseif ( confirmType == LE_SPELL_CONFIRMATION_PROMPT_TYPE_SIMPLE_WARNING ) then
  1418. StaticPopup_Hide("SPELL_CONFIRMATION_WARNING", spellID);
  1419. elseif ( confirmType == LE_SPELL_CONFIRMATION_PROMPT_TYPE_BONUS_ROLL ) then
  1420. BonusRollFrame_CloseBonusRoll();
  1421. end
  1422. elseif ( event == "SAVED_VARIABLES_TOO_LARGE" ) then
  1423. local addonName = ...;
  1424. StaticPopup_Show("SAVED_VARIABLES_TOO_LARGE", addonName);
  1425. elseif ( event == "CONFIRM_DISENCHANT_ROLL" ) then
  1426. local texture, name, count, quality, bindOnPickUp = GetLootRollItemInfo(arg1);
  1427. local dialog = StaticPopup_Show("CONFIRM_LOOT_ROLL", ITEM_QUALITY_COLORS[quality].hex..name.."|r");
  1428. if ( dialog ) then
  1429. dialog.text:SetFormattedText(LOOT_NO_DROP_DISENCHANT, ITEM_QUALITY_COLORS[quality].hex..name.."|r");
  1430. StaticPopup_Resize(dialog, "CONFIRM_LOOT_ROLL");
  1431. dialog.data = arg1;
  1432. dialog.data2 = arg2;
  1433. end
  1434. elseif ( event == "INSTANCE_BOOT_START" ) then
  1435. if (C_Garrison.IsOnGarrisonMap()) then
  1436. StaticPopup_Show("GARRISON_BOOT");
  1437. else
  1438. StaticPopup_Show("INSTANCE_BOOT");
  1439. end
  1440. elseif ( event == "INSTANCE_BOOT_STOP" ) then
  1441. StaticPopup_Hide("INSTANCE_BOOT");
  1442. StaticPopup_Hide("GARRISON_BOOT");
  1443. elseif ( event == "INSTANCE_LOCK_START" ) then
  1444. StaticPopup_Show("INSTANCE_LOCK", nil, nil, true);
  1445. elseif ( event == "INSTANCE_LOCK_STOP" ) then
  1446. StaticPopup_Hide("INSTANCE_LOCK");
  1447. elseif ( event == "INSTANCE_LOCK_WARNING" ) then
  1448. StaticPopup_Show("INSTANCE_LOCK", nil, nil, false);
  1449. elseif ( event == "CONFIRM_TALENT_WIPE" ) then
  1450. HideUIPanel(GossipFrame);
  1451. StaticPopupDialogs["CONFIRM_TALENT_WIPE"].text = _G["CONFIRM_TALENT_WIPE_"..arg2];
  1452. local dialog = StaticPopup_Show("CONFIRM_TALENT_WIPE");
  1453. if ( dialog ) then
  1454. MoneyFrame_Update(dialog:GetName().."MoneyFrame", arg1);
  1455. -- open the talent UI to the player's active talent group...just so the player knows
  1456. -- exactly which talent spec he is wiping
  1457. -- TalentFrame_LoadUI();
  1458. -- if ( PlayerTalentFrame_Open ) then
  1459. -- PlayerTalentFrame_Open(GetActiveSpecGroup());
  1460. -- end
  1461. end
  1462. elseif ( event == "CONFIRM_BINDER" ) then
  1463. StaticPopup_Show("CONFIRM_BINDER", arg1);
  1464. elseif ( event == "CONFIRM_SUMMON" ) then
  1465. local summonType, skipStartingArea = arg1, arg2;
  1466. if ( skipStartingArea ) then -- check if skiping start experience
  1467. StaticPopup_Show("CONFIRM_SUMMON_STARTING_AREA");
  1468. elseif (summonType == LE_SUMMON_REASON_SCENARIO) then
  1469. StaticPopup_Show("CONFIRM_SUMMON_SCENARIO");
  1470. else
  1471. StaticPopup_Show("CONFIRM_SUMMON");
  1472. end
  1473. elseif ( event == "CANCEL_SUMMON" ) then
  1474. StaticPopup_Hide("CONFIRM_SUMMON");
  1475. StaticPopup_Hide("CONFIRM_SUMMON_SCENARIO");
  1476. StaticPopup_Hide("CONFIRM_SUMMON_STARTING_AREA");
  1477. elseif ( event == "BILLING_NAG_DIALOG" ) then
  1478. StaticPopup_Show("BILLING_NAG", arg1);
  1479. elseif ( event == "IGR_BILLING_NAG_DIALOG" ) then
  1480. StaticPopup_Show("IGR_BILLING_NAG");
  1481. elseif ( event == "GOSSIP_CONFIRM" ) then
  1482. if ( arg3 > 0 ) then
  1483. StaticPopupDialogs["GOSSIP_CONFIRM"].hasMoneyFrame = 1;
  1484. else
  1485. StaticPopupDialogs["GOSSIP_CONFIRM"].hasMoneyFrame = nil;
  1486. end
  1487. local dialog = StaticPopup_Show("GOSSIP_CONFIRM", arg2);
  1488. if ( dialog ) then
  1489. dialog.data = arg1;
  1490. if ( arg3 > 0 ) then
  1491. MoneyFrame_Update(dialog:GetName().."MoneyFrame", arg3);
  1492. end
  1493. end
  1494. elseif ( event == "GOSSIP_ENTER_CODE" ) then
  1495. local dialog = StaticPopup_Show("GOSSIP_ENTER_CODE");
  1496. if ( dialog ) then
  1497. dialog.data = arg1;
  1498. end
  1499. elseif ( event == "GOSSIP_CONFIRM_CANCEL" or event == "GOSSIP_CLOSED" ) then
  1500. StaticPopup_Hide("GOSSIP_CONFIRM");
  1501. StaticPopup_Hide("GOSSIP_ENTER_CODE");
  1502. --Events for handling Auction UI
  1503. elseif ( event == "AUCTION_HOUSE_SHOW" ) then
  1504. if ( GameLimitedMode_IsActive() ) then
  1505. UIErrorsFrame:AddExternalErrorMessage(ERR_FEATURE_RESTRICTED_TRIAL);
  1506. C_AuctionHouse.CloseAuctionHouse();
  1507. else
  1508. AuctionHouseFrame_LoadUI();
  1509. ShowUIPanel(AuctionHouseFrame);
  1510. end
  1511. elseif ( event == "AUCTION_HOUSE_CLOSED" ) then
  1512. if ( AuctionHouseFrame ) then
  1513. HideUIPanel(AuctionHouseFrame);
  1514. end
  1515. elseif ( event == "AUCTION_HOUSE_DISABLED" ) then
  1516. StaticPopup_Show("AUCTION_HOUSE_DISABLED");
  1517. -- Events for trainer UI handling
  1518. elseif ( event == "TRAINER_SHOW" ) then
  1519. ClassTrainerFrame_LoadUI();
  1520. if ( ClassTrainerFrame_Show ) then
  1521. ClassTrainerFrame_Show();
  1522. end
  1523. elseif ( event == "TRAINER_CLOSED" ) then
  1524. if ( ClassTrainerFrame_Hide ) then
  1525. ClassTrainerFrame_Hide();
  1526. end
  1527. -- Events for trade skill UI handling
  1528. elseif ( event == "TRADE_SKILL_SHOW" ) then
  1529. TradeSkillFrame_LoadUI();
  1530. ShowUIPanel(TradeSkillFrame);
  1531. elseif ( event == "OBLITERUM_FORGE_SHOW" ) then
  1532. ObliterumForgeFrame_LoadUI();
  1533. ShowUIPanel(ObliterumForgeFrame);
  1534. elseif ( event == "SCRAPPING_MACHINE_SHOW" ) then
  1535. ScrappingMachineFrame_LoadUI();
  1536. ShowUIPanel(ScrappingMachineFrame);
  1537. -- Event for item socketing handling
  1538. elseif ( event == "SOCKET_INFO_UPDATE" ) then
  1539. ItemSocketingFrame_LoadUI();
  1540. ItemSocketingFrame_Update();
  1541. ShowUIPanel(ItemSocketingFrame);
  1542. elseif ( event == "ARTIFACT_UPDATE" ) then
  1543. ArtifactFrame_LoadUI();
  1544. ShowUIPanel(ArtifactFrame);
  1545. elseif ( event == "ARTIFACT_RESPEC_PROMPT" ) then
  1546. ArtifactFrame_LoadUI();
  1547. ShowUIPanel(ArtifactFrame);
  1548. if C_ArtifactUI.GetPointsRemaining() < C_ArtifactUI.GetRespecCost() then
  1549. StaticPopup_Show("NOT_ENOUGH_POWER_ARTIFACT_RESPEC", BreakUpLargeNumbers(C_ArtifactUI.GetRespecCost()));
  1550. else
  1551. StaticPopup_Show("CONFIRM_ARTIFACT_RESPEC", BreakUpLargeNumbers(C_ArtifactUI.GetRespecCost()));
  1552. end
  1553. elseif ( event == "ARTIFACT_ENDGAME_REFUND" ) then
  1554. local numRefunded, refundedTier, bagOrInventorySlot = ...;
  1555. ArtifactFrame_LoadUI();
  1556. ArtifactFrame:OnTraitsRefunded(numRefunded, refundedTier);
  1557. elseif ( event == "ARTIFACT_RELIC_FORGE_UPDATE" ) then
  1558. ArtifactFrame_LoadUI();
  1559. ShowUIPanel(ArtifactRelicForgeFrame);
  1560. elseif ( event == "AZERITE_ESSENCE_FORGE_OPEN" ) then
  1561. UIParentLoadAddOn("Blizzard_AzeriteEssenceUI");
  1562. if AzeriteEssenceUI and AzeriteEssenceUI:TryShow() and AzeriteEssenceUI:ShouldOpenBagsOnShow() then
  1563. OpenAllBags(AzeriteEssenceUI);
  1564. end
  1565. elseif ( event == "ADVENTURE_MAP_OPEN" ) then
  1566. Garrison_LoadUI();
  1567. local followerTypeID = ...;
  1568. if ( followerTypeID == LE_FOLLOWER_TYPE_GARRISON_7_0 ) then
  1569. ShowUIPanel(OrderHallMissionFrame);
  1570. else
  1571. ShowUIPanel(BFAMissionFrame);
  1572. end
  1573. -- Event for BarberShop handling
  1574. elseif ( event == "BARBER_SHOP_OPEN" ) then
  1575. BarberShopFrame_LoadUI();
  1576. if ( BarberShopFrame ) then
  1577. ShowUIPanel(BarberShopFrame);
  1578. end
  1579. elseif ( event == "BARBER_SHOP_CLOSE" ) then
  1580. if ( BarberShopFrame and BarberShopFrame:IsVisible() ) then
  1581. HideUIPanel(BarberShopFrame);
  1582. end
  1583. -- Event for guildbank handling
  1584. elseif ( event == "GUILDBANKFRAME_OPENED" ) then
  1585. GuildBankFrame_LoadUI();
  1586. if ( GuildBankFrame ) then
  1587. ShowUIPanel(GuildBankFrame);
  1588. if ( not GuildBankFrame:IsVisible() ) then
  1589. CloseGuildBankFrame();
  1590. end
  1591. end
  1592. elseif ( event == "GUILDBANKFRAME_CLOSED" ) then
  1593. if ( GuildBankFrame ) then
  1594. HideUIPanel(GuildBankFrame);
  1595. end
  1596. -- Display instance reset info
  1597. elseif ( event == "RAID_INSTANCE_WELCOME" ) then
  1598. local dungeonName = arg1;
  1599. local lockExpireTime = arg2;
  1600. local locked = arg3;
  1601. local extended = arg4;
  1602. local message;
  1603. if ( locked == 0 ) then
  1604. message = format(RAID_INSTANCE_WELCOME, dungeonName, SecondsToTime(lockExpireTime, nil, 1))
  1605. else
  1606. if ( lockExpireTime == 0 ) then
  1607. message = format(RAID_INSTANCE_WELCOME_EXTENDED, dungeonName);
  1608. else
  1609. if ( extended == 0 ) then
  1610. message = format(RAID_INSTANCE_WELCOME_LOCKED, dungeonName, SecondsToTime(lockExpireTime, nil, 1));
  1611. else
  1612. message = format(RAID_INSTANCE_WELCOME_LOCKED_EXTENDED, dungeonName, SecondsToTime(lockExpireTime, nil, 1));
  1613. end
  1614. end
  1615. end
  1616. local info = ChatTypeInfo["SYSTEM"];
  1617. DEFAULT_CHAT_FRAME:AddMessage(message, info.r, info.g, info.b, info.id);
  1618. -- Events for taxi benchmarking
  1619. elseif ( event == "ENABLE_TAXI_BENCHMARK" ) then
  1620. if ( not FramerateText:IsShown() ) then
  1621. ToggleFramerate(true);
  1622. end
  1623. local info = ChatTypeInfo["SYSTEM"];
  1624. DEFAULT_CHAT_FRAME:AddMessage(BENCHMARK_TAXI_MODE_ON, info.r, info.g, info.b, info.id);
  1625. elseif ( event == "DISABLE_TAXI_BENCHMARK" ) then
  1626. if ( FramerateText.benchmark ) then
  1627. ToggleFramerate();
  1628. end
  1629. local info = ChatTypeInfo["SYSTEM"];
  1630. DEFAULT_CHAT_FRAME:AddMessage(BENCHMARK_TAXI_MODE_OFF, info.r, info.g, info.b, info.id);
  1631. elseif ( event == "CHAT_MSG_WHISPER" and arg6 == "GM" ) then --GMChatUI
  1632. GMChatFrame_LoadUI(event, ...);
  1633. elseif ( event == "WOW_MOUSE_NOT_FOUND" ) then
  1634. StaticPopup_Show("WOW_MOUSE_NOT_FOUND");
  1635. elseif ( event == "TALENTS_INVOLUNTARILY_RESET" ) then
  1636. if ( arg1 ) then
  1637. StaticPopup_Show("TALENTS_INVOLUNTARILY_RESET_PET");
  1638. else
  1639. StaticPopup_Show("TALENTS_INVOLUNTARILY_RESET");
  1640. end
  1641. elseif (event == "SPEC_INVOLUNTARILY_CHANGED" ) then
  1642. StaticPopup_Show("SPEC_INVOLUNTARILY_CHANGED")
  1643. elseif( event == "EXPERIMENTAL_CVAR_CONFIRMATION_NEEDED" ) then
  1644. StaticPopup_Show("EXPERIMENTAL_CVAR_WARNING");
  1645. elseif ( event == "BAG_OVERFLOW_WITH_FULL_INVENTORY") then
  1646. StaticPopup_Show("CLIENT_INVENTORY_FULL_OVERFLOW");
  1647. elseif ( event == "AUCTION_HOUSE_SCRIPT_DEPRECATED") then
  1648. StaticPopup_Show("AUCTION_HOUSE_DEPRECATED");
  1649. -- Events for Archaeology
  1650. elseif ( event == "ARCHAEOLOGY_TOGGLE" ) then
  1651. ArchaeologyFrame_LoadUI();
  1652. if ( ArchaeologyFrame_Show and not ArchaeologyFrame:IsShown()) then
  1653. ArchaeologyFrame_Show();
  1654. elseif ( ArchaeologyFrame_Hide ) then
  1655. ArchaeologyFrame_Hide();
  1656. end
  1657. elseif ( event == "ARCHAEOLOGY_SURVEY_CAST" ) then
  1658. ArchaeologyFrame_LoadUI();
  1659. ArcheologyDigsiteProgressBar_OnEvent(ArcheologyDigsiteProgressBar, event, ...);
  1660. self:UnregisterEvent("ARCHAEOLOGY_SURVEY_CAST");
  1661. -- Events for Transmogrify UI handling
  1662. elseif ( event == "TRANSMOGRIFY_OPEN" ) then
  1663. CollectionsJournal_LoadUI();
  1664. if ( WardrobeFrame ) then
  1665. ShowUIPanel(WardrobeFrame);
  1666. end
  1667. elseif ( event == "TRANSMOGRIFY_CLOSE" ) then
  1668. if ( WardrobeFrame ) then
  1669. HideUIPanel(WardrobeFrame);
  1670. end
  1671. -- Events for adventure journal
  1672. elseif ( event == "AJ_OPEN" ) then
  1673. if (C_AdventureJournal.CanBeShown()) then
  1674. if ( not EncounterJournal ) then
  1675. EncounterJournal_LoadUI();
  1676. end
  1677. ShowUIPanel(EncounterJournal);
  1678. EJSuggestFrame_OpenFrame();
  1679. end
  1680. -- Events for Void Storage UI handling
  1681. elseif ( event == "VOID_STORAGE_OPEN" ) then
  1682. VoidStorage_LoadUI();
  1683. if ( VoidStorageFrame_Show ) then
  1684. VoidStorageFrame_Show();
  1685. end
  1686. elseif ( event == "VOID_STORAGE_CLOSE" ) then
  1687. if ( VoidStorageFrame_Hide ) then
  1688. VoidStorageFrame_Hide();
  1689. end
  1690. --Events for Trial caps
  1691. elseif ( event == "TRIAL_CAP_REACHED_MONEY" ) then
  1692. TrialAccountCapReached_Inform("money");
  1693. elseif ( event == "TRIAL_CAP_REACHED_LEVEL" ) then
  1694. TrialAccountCapReached_Inform("level");
  1695. -- Events for Black Market UI handling
  1696. elseif ( event == "BLACK_MARKET_OPEN" ) then
  1697. BlackMarket_LoadUI();
  1698. if ( BlackMarketFrame_Show ) then
  1699. BlackMarketFrame_Show();
  1700. end
  1701. elseif ( event == "BLACK_MARKET_CLOSE" ) then
  1702. if ( BlackMarketFrame_Hide ) then
  1703. BlackMarketFrame_Hide();
  1704. end
  1705. -- Events for Item Upgrading
  1706. elseif ( event == "ITEM_UPGRADE_MASTER_OPENED" ) then
  1707. ItemUpgrade_LoadUI();
  1708. if ( ItemUpgradeFrame_Show ) then
  1709. ItemUpgradeFrame_Show();
  1710. end
  1711. elseif ( event == "ITEM_UPGRADE_MASTER_CLOSED" ) then
  1712. if ( ItemUpgradeFrame_Hide ) then
  1713. ItemUpgradeFrame_Hide();
  1714. end
  1715. -- Events for Toy Box
  1716. elseif ( event == "TOYS_UPDATED" ) then
  1717. if ( not CollectionsJournal ) then
  1718. local itemID, new = ...;
  1719. if ( itemID and new ) then
  1720. -- Toy box isn't loaded, save that this itemid is new in this session incase the journal is opened later
  1721. if not self.newToys then
  1722. self.newToys = {};
  1723. end
  1724. self.newToys[itemID] = true;
  1725. self.autoPageToCollectedToyID = itemID;
  1726. SetCVar("petJournalTab", COLLECTIONS_JOURNAL_TAB_INDEX_TOYS);
  1727. end
  1728. end
  1729. -- Events for Heirloom Journal
  1730. elseif ( event == "HEIRLOOM_UPGRADE_TARGETING_CHANGED" ) then
  1731. local isPendingHeirloomUpgrade = ...;
  1732. if ( isPendingHeirloomUpgrade ) then
  1733. if ( not CollectionsJournal ) then
  1734. CollectionsJournal_LoadUI();
  1735. end
  1736. HeirloomsJournal:SetFindClosestUpgradeablePage(isPendingHeirloomUpgrade);
  1737. ShowUIPanel(CollectionsJournal);
  1738. CollectionsJournal_SetTab(CollectionsJournal, 4);
  1739. end
  1740. elseif ( event == "HEIRLOOMS_UPDATED" ) then
  1741. if ( not CollectionsJournal ) then
  1742. local itemID, updateReason = ...;
  1743. if ( itemID and updateReason == "NEW" ) then
  1744. -- Heirloom journal isn't loaded, save that this itemid is new in this session incase the journal is opened later
  1745. if not self.newHeirlooms then
  1746. self.newHeirlooms = {};
  1747. end
  1748. self.newHeirlooms[itemID] = true;
  1749. end
  1750. end
  1751. -- Events for Wardrobe
  1752. elseif ( event == "TRANSMOG_COLLECTION_UPDATED" ) then
  1753. if ( not CollectionsJournal ) then
  1754. local latestAppearanceID, latestAppearanceCategoryID = C_TransmogCollection.GetLatestAppearance();
  1755. if ( latestAppearanceID and latestAppearanceID ~= self.latestAppearanceID ) then
  1756. self.latestAppearanceID = latestAppearanceID;
  1757. SetCVar("petJournalTab", 5);
  1758. end
  1759. end
  1760. -- Quest Choice trigger event
  1761. elseif ( event == "QUEST_CHOICE_UPDATE" ) then
  1762. local choiceInfo = C_QuestChoice.GetQuestChoiceInfo();
  1763. if (choiceInfo.uiTextureKitID and choiceInfo.uiTextureKitID ~= 0) then
  1764. WarboardQuestChoice_LoadUI();
  1765. WarboardQuestChoiceFrame:TryShow();
  1766. else
  1767. QuestChoice_LoadUI();
  1768. QuestChoiceFrame:TryShow();
  1769. end
  1770. elseif ( event == "LUA_WARNING" ) then
  1771. HandleLuaWarning(...);
  1772. elseif ( event == "GARRISON_ARCHITECT_OPENED") then
  1773. if (not GarrisonBuildingFrame) then
  1774. Garrison_LoadUI();
  1775. end
  1776. ShowUIPanel(GarrisonBuildingFrame);
  1777. elseif ( event == "GARRISON_ARCHITECT_CLOSED" ) then
  1778. if ( GarrisonBuildingFrame ) then
  1779. HideUIPanel(GarrisonBuildingFrame);
  1780. end
  1781. elseif ( event == "GARRISON_MISSION_NPC_OPENED") then
  1782. local followerType = ...;
  1783. if followerType ~= LE_FOLLOWER_TYPE_GARRISON_7_0 then
  1784. local frameName = GarrisonFollowerOptions[followerType].missionFrame;
  1785. if (not _G[frameName]) then
  1786. Garrison_LoadUI();
  1787. end
  1788. local frame = _G[frameName];
  1789. frame.followerTypeID = followerType;
  1790. ShowUIPanel(frame);
  1791. end
  1792. elseif ( event == "GARRISON_MISSION_NPC_CLOSED" ) then
  1793. if ( GarrisonMissionFrame ) then
  1794. HideUIPanel(GarrisonMissionFrame);
  1795. end
  1796. if ( BFAMissionFrame ) then
  1797. HideUIPanel(BFAMissionFrame);
  1798. end
  1799. elseif ( event == "GARRISON_SHIPYARD_NPC_OPENED") then
  1800. if (not GarrisonShipyardFrame) then
  1801. Garrison_LoadUI();
  1802. end
  1803. GarrisonShipyardFrame.followerTypeID = ...;
  1804. ShowUIPanel(GarrisonShipyardFrame);
  1805. elseif ( event == "GARRISON_SHIPYARD_NPC_CLOSED" ) then
  1806. if ( GarrisonShipyardFrame ) then
  1807. HideUIPanel(GarrisonShipyardFrame);
  1808. end
  1809. elseif ( event == "SHIPMENT_CRAFTER_OPENED" ) then
  1810. if (not GarrisonCapacitiveDisplayFrame) then
  1811. Garrison_LoadUI();
  1812. end
  1813. elseif ( event == "GARRISON_MONUMENT_SHOW_UI") then
  1814. if(not GarrisonMonumentFrame)then
  1815. Garrison_LoadUI();
  1816. end
  1817. GarrisonMonuntmentFrame_OnEvent(GarrisonMonumentFrame, event, ...);
  1818. elseif ( event == "GARRISON_RECRUITMENT_NPC_OPENED") then
  1819. if(not GarrisonRecruiterFrame)then
  1820. Garrison_LoadUI();
  1821. end
  1822. ShowUIPanel(GarrisonRecruiterFrame);
  1823. elseif ( event == "GARRISON_TALENT_NPC_OPENED") then
  1824. OrderHall_LoadUI();
  1825. OrderHallTalentFrame:SetGarrisonType(...);
  1826. ToggleOrderHallTalentUI();
  1827. elseif ( event == "PRODUCT_DISTRIBUTIONS_UPDATED" ) then
  1828. StoreFrame_CheckForFree(event);
  1829. elseif ( event == "LOADING_SCREEN_ENABLED" ) then
  1830. TopBannerManager_LoadingScreenEnabled();
  1831. elseif ( event == "LOADING_SCREEN_DISABLED" ) then
  1832. TopBannerManager_LoadingScreenDisabled()
  1833. elseif ( event == "TOKEN_AUCTION_SOLD" ) then
  1834. local info = ChatTypeInfo["SYSTEM"];
  1835. local itemName = GetItemInfo(WOW_TOKEN_ITEM_ID);
  1836. if (itemName) then
  1837. DEFAULT_CHAT_FRAME:AddMessage(ERR_AUCTION_SOLD_S:format(itemName), info.r, info.g, info.b, info.id);
  1838. else
  1839. self:RegisterEvent("GET_ITEM_INFO_RECEIVED");
  1840. end
  1841. elseif ( event == "GET_ITEM_INFO_RECEIVED" ) then
  1842. local itemID = ...;
  1843. if (itemID == WOW_TOKEN_ITEM_ID) then
  1844. local info = ChatTypeInfo["SYSTEM"];
  1845. local itemName = GetItemInfo(WOW_TOKEN_ITEM_ID);
  1846. DEFAULT_CHAT_FRAME:AddMessage(ERR_AUCTION_SOLD_S:format(itemName), info.r, info.g, info.b, info.id);
  1847. self:UnregisterEvent("GET_ITEM_INFO_RECEIVED");
  1848. end
  1849. elseif ( event == "TALKINGHEAD_REQUESTED" ) then
  1850. if ( not TalkingHeadFrame ) then
  1851. TalkingHead_LoadUI();
  1852. TalkingHeadFrame_PlayCurrent();
  1853. end
  1854. self:UnregisterEvent("TALKINGHEAD_REQUESTED");
  1855. elseif (event == "CHALLENGE_MODE_KEYSTONE_RECEPTABLE_OPEN") then
  1856. ChallengeMode_LoadUI();
  1857. ChallengesKeystoneFrame:ShowKeystoneFrame();
  1858. elseif (event == "CHALLENGE_MODE_COMPLETED") then
  1859. if (not ChallengeModeCompleteBanner) then
  1860. ChallengeMode_LoadUI();
  1861. ChallengeModeCompleteBanner:OnEvent(event, ...);
  1862. end
  1863. self:UnregisterEvent("CHALLENGE_MODE_COMPLETED");
  1864. elseif (event == "UNIT_AURA") then
  1865. OrderHall_CheckCommandBar();
  1866. elseif (event == "TAXIMAP_OPENED") then
  1867. local uiMapSystem = ...;
  1868. if (uiMapSystem == Enum.UIMapSystem.Taxi) then
  1869. ShowUIPanel(TaxiFrame);
  1870. else
  1871. FlightMap_LoadUI();
  1872. ShowUIPanel(FlightMapFrame);
  1873. end
  1874. elseif (event == "SCENARIO_UPDATE") then
  1875. BoostTutorial_AttemptLoad();
  1876. elseif (event == "DEBUG_MENU_TOGGLED") then
  1877. UpdateUIParentRelativeToDebugMenu();
  1878. elseif (event == "REVEAL_CAPTURE_TOGGLED") then
  1879. UpdateUIParentRelativeToDebugMenu();
  1880. elseif ( event == "GROUP_INVITE_CONFIRMATION" ) then
  1881. UpdateInviteConfirmationDialogs();
  1882. elseif ( event == "INVITE_TO_PARTY_CONFIRMATION" ) then
  1883. OnInviteToPartyConfirmation(...);
  1884. elseif ( event == "CONTRIBUTION_COLLECTOR_OPEN" ) then
  1885. UIParentLoadAddOn("Blizzard_Contribution");
  1886. ContributionCollectionUI_Show();
  1887. elseif (event == "CONTRIBUTION_COLLECTOR_CLOSE" ) then
  1888. if ( ContributionCollectionUI_Hide ) then
  1889. ContributionCollectionUI_Hide();
  1890. end
  1891. elseif (event == "ALLIED_RACE_OPEN") then
  1892. AlliedRaces_LoadUI();
  1893. local raceID = ...;
  1894. AlliedRacesFrame:LoadRaceData(raceID);
  1895. ShowUIPanel(AlliedRacesFrame);
  1896. elseif (event == "ISLAND_COMPLETED") then
  1897. IslandsPartyPose_LoadUI();
  1898. local mapID, winner = ...;
  1899. IslandsPartyPoseFrame:LoadScreen(mapID, winner);
  1900. ShowUIPanel(IslandsPartyPoseFrame);
  1901. elseif (event == "WARFRONT_COMPLETED") then
  1902. WarfrontsPartyPose_LoadUI();
  1903. local mapID, winner = ...;
  1904. WarfrontsPartyPoseFrame:LoadScreen(mapID, winner);
  1905. ShowUIPanel(WarfrontsPartyPoseFrame);
  1906. -- Event(s) for Azerite Respec
  1907. elseif (event == "RESPEC_AZERITE_EMPOWERED_ITEM_OPENED") then
  1908. AzeriteRespecFrame_LoadUI();
  1909. ShowUIPanel(AzeriteRespecFrame);
  1910. elseif (event == "ISLANDS_QUEUE_OPEN") then
  1911. IslandsQueue_LoadUI();
  1912. ShowUIPanel(IslandsQueueFrame);
  1913. elseif (event == "ITEM_INTERACTION_OPEN") then
  1914. ItemInteraction_LoadUI();
  1915. ShowUIPanel(ItemInteractionFrame);
  1916. -- Events for Reporting system
  1917. elseif (event == "REPORT_PLAYER_RESULT") then
  1918. local success = ...;
  1919. if (success) then
  1920. UIErrorsFrame:AddExternalErrorMessage(GERR_REPORT_SUBMITTED_SUCCESSFULLY);
  1921. DEFAULT_CHAT_FRAME:AddMessage(COMPLAINT_ADDED);
  1922. else
  1923. UIErrorsFrame:AddExternalErrorMessage(GERR_REPORT_SUBMISSION_FAILED);
  1924. DEFAULT_CHAT_FRAME:AddMessage(ERR_REPORT_SUBMISSION_FAILED);
  1925. end
  1926. elseif (event == "GLOBAL_MOUSE_DOWN" or event == "GLOBAL_MOUSE_UP") then
  1927. local buttonID = ...;
  1928. -- Close dropdown(s).
  1929. local mouseFocus = GetMouseFocus();
  1930. if not HandlesGlobalMouseEvent(mouseFocus, buttonID, event) then
  1931. UIDropDownMenu_HandleGlobalMouseEvent(buttonID, event);
  1932. end
  1933. -- Clear keyboard focus.
  1934. local autoCompleteBoxList = { AutoCompleteBox }
  1935. if LFGListFrame and LFGListFrame.SearchPanel and LFGListFrame.SearchPanel.AutoCompleteFrame then
  1936. tinsert(autoCompleteBoxList, LFGListFrame.SearchPanel.AutoCompleteFrame);
  1937. end
  1938. if not HasVisibleAutoCompleteBox(autoCompleteBoxList, mouseFocus) then
  1939. if event == "GLOBAL_MOUSE_DOWN" and buttonID == "LeftButton" and not IsModifierKeyDown() then
  1940. local keyBoardFocus = GetCurrentKeyBoardFocus();
  1941. if keyBoardFocus then
  1942. local hasStickyFocus = keyBoardFocus.HasStickyFocus and keyBoardFocus:HasStickyFocus();
  1943. if keyBoardFocus.ClearFocus and not hasStickyFocus and keyBoardFocus ~= mouseFocus then
  1944. keyBoardFocus:ClearFocus();
  1945. end
  1946. end
  1947. end
  1948. end
  1949. end
  1950. end
  1951. -- Frame Management --
  1952. -- UIPARENT_MANAGED_FRAME_POSITIONS stores all the frames that have positioning dependencies based on other frames.
  1953. -- UIPARENT_MANAGED_FRAME_POSITIONS["FRAME"] = {
  1954. --Note: this is out of date and there are several more options now.
  1955. -- none = This value is used if no dependent frames are shown
  1956. -- watchBar = This is the offset used if the reputation or artifact watch bar is shown
  1957. -- anchorTo = This is the object that the stored frame is anchored to
  1958. -- point = This is the point on the frame used as the anchor
  1959. -- rpoint = This is the point on the "anchorTo" frame that the stored frame is anchored to
  1960. -- bottomEither = This offset is used if either bottom multibar is shown
  1961. -- bottomLeft
  1962. -- var = If this is set use _G[varName] = value instead of setpoint
  1963. -- };
  1964. -- some standard offsets
  1965. local actionBarOffset = 45;
  1966. local menuBarTop = 55;
  1967. local overrideActionBarTop = 40;
  1968. local petBattleTop = 60;
  1969. function UpdateMenuBarTop ()
  1970. --Determines the optimal magic number based on resolution and action bar status.
  1971. menuBarTop = 55;
  1972. local width = GetScreenWidth();
  1973. local height = GetScreenHeight();
  1974. if ( ( width / height ) > 4/3 ) then
  1975. --Widescreen resolution
  1976. menuBarTop = 75;
  1977. end
  1978. end
  1979. function UIParent_UpdateTopFramePositions()
  1980. local topOffset = 0;
  1981. local buffsAreaTopOffset = 0;
  1982. if (OrderHallCommandBar and OrderHallCommandBar:IsShown()) then
  1983. topOffset = 12;
  1984. buffsAreaTopOffset = OrderHallCommandBar:GetHeight();
  1985. end
  1986. if (PlayerFrame and not PlayerFrame:IsUserPlaced() and not PlayerFrame_IsAnimatedOut(PlayerFrame)) then
  1987. PlayerFrame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", -19, -4 - topOffset)
  1988. end
  1989. if (TargetFrame and not TargetFrame:IsUserPlaced()) then
  1990. TargetFrame:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 250, -4 - topOffset);
  1991. end
  1992. local ticketStatusFrameShown = TicketStatusFrame and TicketStatusFrame:IsShown();
  1993. local gmChatStatusFrameShown = GMChatStatusFrame and GMChatStatusFrame:IsShown();
  1994. if (ticketStatusFrameShown) then
  1995. TicketStatusFrame:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT", -180, 0 - buffsAreaTopOffset);
  1996. buffsAreaTopOffset = buffsAreaTopOffset + TicketStatusFrame:GetHeight();
  1997. end
  1998. if (gmChatStatusFrameShown) then
  1999. GMChatStatusFrame:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT", -170, -5 - buffsAreaTopOffset);
  2000. buffsAreaTopOffset = buffsAreaTopOffset + GMChatStatusFrame:GetHeight() + 5;
  2001. end
  2002. if (not ticketStatusFrameShown and not gmChatStatusFrameShown) then
  2003. buffsAreaTopOffset = buffsAreaTopOffset + 13;
  2004. end
  2005. BuffFrame:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT", -205, 0 - buffsAreaTopOffset);
  2006. end
  2007. UIPARENT_ALTERNATE_FRAME_POSITIONS = {
  2008. ["PlayerPowerBarAlt_Bottom"] = {baseY = true, yOffset = 20, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, reputation = 1, tutorialAlert = 1, extraActionBarFrame = 1, ZoneAbilityFrame = 1};
  2009. ["PlayerPowerBarAlt_Top"] = {baseY = -30, anchorTo = "UIParent", point = "TOP", rpoint = "TOP"};
  2010. }
  2011. UIPARENT_MANAGED_FRAME_POSITIONS = {
  2012. --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.
  2013. --"yOffset" gets added to the value of "baseY", which is used for values based on menuBarTop.
  2014. ["MultiBarBottomLeft"] = {baseY = 13, watchBar = 1, maxLevel = 1, anchorTo = "ActionButton1", point = "BOTTOMLEFT", rpoint = "TOPLEFT"};
  2015. ["MultiBarBottomRight"] = {baseY = 2, watchBar = 1, maxLevel = 1, anchorTo = "ActionButton12", point = "TOPLEFT", rpoint = "TOPRIGHT", xOffset = 45};
  2016. ["GroupLootContainer"] = {baseY = true, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, watchBar = 1};
  2017. ["TutorialFrameAlertButton"] = {baseY = true, yOffset = -10, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, watchBar = 1};
  2018. ["FramerateLabel"] = {baseY = true, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, watchBar = 1, playerPowerBarAlt = 1, powerBarWidgets = 1, extraActionBarFrame = 1, anchorTo="WorldFrame" };
  2019. ["ArcheologyDigsiteProgressBar"] = {baseY = true, yOffset = 40, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, watchBar = 1, tutorialAlert = 1, playerPowerBarAlt = 1, powerBarWidgets = 1, extraActionBarFrame = 1, ZoneAbilityFrame = 1, castingBar = 1};
  2020. ["CastingBarFrame"] = {baseY = true, yOffset = 40, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, watchBar = 1, tutorialAlert = 1, playerPowerBarAlt = 1, powerBarWidgets = 1, extraActionBarFrame = 1, ZoneAbilityFrame = 1, talkingHeadFrame = 1, classResourceOverlayFrame = 1, classResourceOverlayOffset = 1};
  2021. ["UIWidgetPowerBarContainerFrame"] = {baseY = true, yOffset = 20, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, watchBar = 1, tutorialAlert = 1, playerPowerBarAlt = 1, extraActionBarFrame = 1, ZoneAbilityFrame = 1, talkingHeadFrame = 1, classResourceOverlayFrame = 1, classResourceOverlayOffset = 1};
  2022. ["ClassResourceOverlayParentFrame"] = {baseY = true, yOffset = 0, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, watchBar = 1, tutorialAlert = 1, playerPowerBarAlt = 1, powerBarWidgets = 1, extraActionBarFrame = 1, ZoneAbilityFrame = 1 };
  2023. ["PlayerPowerBarAlt"] = UIPARENT_ALTERNATE_FRAME_POSITIONS["PlayerPowerBarAlt_Bottom"];
  2024. ["ExtraActionBarFrame"] = {baseY = true, yOffset = 0, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, watchBar = 1, tutorialAlert = 1};
  2025. ["ZoneAbilityFrame"] = {baseY = true, yOffset = 0, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, watchBar = 1, tutorialAlert = 1, extraActionBarFrame = 1};
  2026. ["ChatFrame1"] = {baseY = true, yOffset = 40, bottomLeft = actionBarOffset-8, justBottomRightAndStance = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, watchBar = 1, maxLevel = 1, point = "BOTTOMLEFT", rpoint = "BOTTOMLEFT", xOffset = 32};
  2027. ["ChatFrame2"] = {baseY = true, yOffset = 40, bottomRight = actionBarOffset-8, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, rightLeft = -2*actionBarOffset, rightRight = -actionBarOffset, watchBar = 1, maxLevel = 1, point = "BOTTOMRIGHT", rpoint = "BOTTOMRIGHT", xOffset = -32};
  2028. ["StanceBarFrame"] = {baseY = 0, bottomLeft = actionBarOffset, watchBar = 1, maxLevel = 1, anchorTo = "MainMenuBar", point = "BOTTOMLEFT", rpoint = "TOPLEFT", xOffset = 30};
  2029. ["PossessBarFrame"] = {baseY = 0, bottomLeft = actionBarOffset, watchBar = 1, maxLevel = 1, anchorTo = "MainMenuBar", point = "BOTTOMLEFT", rpoint = "TOPLEFT", xOffset = 30};
  2030. ["MultiCastActionBarFrame"] = {baseY = 8, bottomLeft = actionBarOffset, watchBar = 1, maxLevel = 1, anchorTo = "MainMenuBar", point = "BOTTOMLEFT", rpoint = "TOPLEFT", xOffset = 30};
  2031. ["AuctionHouseMultisellProgressFrame"] = {baseY = true, yOffset = 18, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, watchBar = 1, tutorialAlert = 1};
  2032. ["TalkingHeadFrame"] = {baseY = true, yOffset = 0, bottomEither = actionBarOffset, overrideActionBar = overrideActionBarTop, petBattleFrame = petBattleTop, bonusActionBar = 1, pet = 1, watchBar = 1, tutorialAlert = 1, playerPowerBarAlt = 1, powerBarWidgets = 1, extraActionBarFrame = 1, ZoneAbilityFrame = 1, classResourceOverlayFrame = 1};
  2033. -- Vars
  2034. -- 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
  2035. -- 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
  2036. -- 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.
  2037. ["CONTAINER_OFFSET_X"] = {baseX = 0, rightActionBarsX = "variable", isVar = "xAxis"};
  2038. ["CONTAINER_OFFSET_Y"] = {baseY = true, yOffset = 10, bottomEither = actionBarOffset, watchBar = 1, isVar = "yAxis"};
  2039. ["PETACTIONBAR_YPOS"] = {baseY = 89, bottomLeft = actionBarOffset + 3, justBottomRightAndStance = actionBarOffset, watchBar = 1, maxLevel = 1, isVar = "yAxis"};
  2040. ["MULTICASTACTIONBAR_YPOS"] = {baseY = 0, bottomLeft = actionBarOffset, watchBar = 1, maxLevel = 1, isVar = "yAxis"};
  2041. ["OBJTRACKER_OFFSET_X"] = {baseX = 12, rightActionBarsX = "variable", isVar = "xAxis"};
  2042. ["BATTLEFIELD_TAB_OFFSET_Y"] = {baseY = 260, bottomRight = actionBarOffset, watchBar = 1, isVar = "yAxis"};
  2043. };
  2044. local UIPARENT_VARIABLE_OFFSETS = {
  2045. ["rightActionBarsX"] = 0,
  2046. };
  2047. -- 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.
  2048. -- The reason why is that it is possible for UIParent_ManageFramePosition to be run before the addon loads.
  2049. OBJTRACKER_OFFSET_X = 0;
  2050. BATTLEFIELD_TAB_OFFSET_Y = 0;
  2051. -- constant offsets
  2052. for _, data in pairs(UIPARENT_MANAGED_FRAME_POSITIONS) do
  2053. for flag, value in pairs(data) do
  2054. if ( flag == "watchBar" ) then
  2055. data[flag] = value * -2;
  2056. elseif ( flag == "maxLevel" ) then
  2057. data[flag] = value * -5;
  2058. elseif ( flag == "pet" ) then
  2059. data[flag] = value * 35;
  2060. elseif ( flag == "tutorialAlert" ) then
  2061. data[flag] = value * 35;
  2062. end
  2063. end
  2064. end
  2065. function UIParent_ManageFramePosition(index, value, yOffsetFrames, xOffsetFrames, hasBottomLeft, hasBottomRight, hasPetBar)
  2066. local frame, xOffset, yOffset, anchorTo, point, rpoint;
  2067. frame = _G[index];
  2068. if ( not frame or (type(frame)=="table" and frame.ignoreFramePositionManager)) then
  2069. return;
  2070. end
  2071. -- Always start with base as the base offset or default to zero if no "none" specified
  2072. xOffset = 0;
  2073. if ( value["baseX"] ) then
  2074. xOffset = value["baseX"];
  2075. elseif ( value["xOffset"] ) then
  2076. xOffset = value["xOffset"];
  2077. end
  2078. yOffset = 0;
  2079. if ( tonumber(value["baseY"]) ) then
  2080. --tonumber(nil) and tonumber(boolean) evaluate as nil, tonumber(number) evaluates as a number, which evaluates as true.
  2081. --This allows us to use the true value in baseY for flagging a frame's positioning as dependent upon the value of menuBarTop.
  2082. yOffset = value["baseY"];
  2083. elseif ( value["baseY"] ) then
  2084. --value["baseY"] is true, use menuBarTop.
  2085. yOffset = menuBarTop;
  2086. end
  2087. if ( value["yOffset"] ) then
  2088. --This is so things based on menuBarTop can still have an offset. Otherwise you'd just use put the offset value in baseY.
  2089. yOffset = yOffset + value["yOffset"];
  2090. end
  2091. -- Iterate through frames that affect y offsets
  2092. local hasBottomEitherFlag;
  2093. for _, flag in pairs(yOffsetFrames) do
  2094. local flagValue = value[flag];
  2095. if ( flagValue ) then
  2096. if ( flagValue == "variable" ) then
  2097. yOffset = yOffset + UIPARENT_VARIABLE_OFFSETS[flag];
  2098. else
  2099. if ( flag == "bottomEither" ) then
  2100. hasBottomEitherFlag = 1;
  2101. end
  2102. yOffset = yOffset + flagValue;
  2103. end
  2104. end
  2105. end
  2106. -- don't offset for the pet bar and bottomEither if the player has
  2107. -- the bottom right bar shown and not the bottom left
  2108. if ( hasBottomEitherFlag and hasBottomRight and hasPetBar and not hasBottomLeft ) then
  2109. yOffset = yOffset - (value["pet"] or 0);
  2110. end
  2111. -- Iterate through frames that affect x offsets
  2112. for _, flag in pairs(xOffsetFrames) do
  2113. local flagValue = value[flag];
  2114. if ( flagValue ) then
  2115. if ( flagValue == "variable" ) then
  2116. xOffset = xOffset + UIPARENT_VARIABLE_OFFSETS[flag];
  2117. else
  2118. xOffset = xOffset + flagValue;
  2119. end
  2120. end
  2121. end
  2122. -- Set up anchoring info
  2123. anchorTo = value["anchorTo"];
  2124. point = value["point"];
  2125. rpoint = value["rpoint"];
  2126. if ( not anchorTo ) then
  2127. anchorTo = "UIParent";
  2128. end
  2129. if ( not point ) then
  2130. point = "BOTTOM";
  2131. end
  2132. if ( not rpoint ) then
  2133. rpoint = "BOTTOM";
  2134. end
  2135. -- Anchor frame
  2136. if ( value["isVar"] ) then
  2137. if ( value["isVar"] == "xAxis" ) then
  2138. _G[index] = xOffset;
  2139. else
  2140. _G[index] = yOffset;
  2141. end
  2142. else
  2143. if ( frame ~= ChatFrame2 and not(frame:IsObjectType("frame") and frame:IsUserPlaced()) ) then
  2144. frame:SetPoint(point, anchorTo, rpoint, xOffset, yOffset);
  2145. end
  2146. end
  2147. end
  2148. local function FramePositionDelegate_OnAttributeChanged(self, attribute)
  2149. if ( attribute == "panel-show" ) then
  2150. local force = self:GetAttribute("panel-force");
  2151. local frame = self:GetAttribute("panel-frame");
  2152. self:ShowUIPanel(frame, force);
  2153. elseif ( attribute == "panel-hide" ) then
  2154. local frame = self:GetAttribute("panel-frame");
  2155. local skipSetPoint = self:GetAttribute("panel-skipSetPoint");
  2156. self:HideUIPanel(frame, skipSetPoint);
  2157. elseif ( attribute == "panel-update" ) then
  2158. local frame = self:GetAttribute("panel-frame");
  2159. self:UpdateUIPanelPositions(frame);
  2160. elseif ( attribute == "uiparent-manage" ) then
  2161. self:UIParentManageFramePositions();
  2162. elseif ( attribute == "panel-maximize" ) then
  2163. local frame = self:GetAttribute("panel-frame");
  2164. self:MoveUIPanel(GetUIPanelWindowInfo(frame, "area"), "fullscreen", UIPANEL_DO_SET_POINT, UIPANEL_VALIDATE_CURRENT_FRAME);
  2165. frame:ClearAllPoints();
  2166. frame:SetPoint(GetUIPanelWindowInfo(frame, "maximizePoint"));
  2167. elseif ( attribute == "panel-restore" ) then
  2168. local frame = self:GetAttribute("panel-frame");
  2169. self:MoveUIPanel("fullscreen", GetUIPanelWindowInfo(frame, "area"), UIPANEL_DO_SET_POINT, UIPANEL_VALIDATE_CURRENT_FRAME);
  2170. end
  2171. end
  2172. local FramePositionDelegate = CreateFrame("FRAME");
  2173. FramePositionDelegate:SetScript("OnAttributeChanged", FramePositionDelegate_OnAttributeChanged);
  2174. function FramePositionDelegate:ShowUIPanel(frame, force)
  2175. local frameArea, framePushable;
  2176. frameArea = GetUIPanelWindowInfo(frame, "area");
  2177. if ( not CanOpenPanels() and frameArea ~= "center" and frameArea ~= "full" ) then
  2178. self:ShowUIPanelFailed(frame);
  2179. return;
  2180. end
  2181. framePushable = GetUIPanelWindowInfo(frame, "pushable") or 0;
  2182. if ( UnitIsDead("player") and not GetUIPanelWindowInfo(frame, "whileDead") ) then
  2183. self:ShowUIPanelFailed(frame);
  2184. NotWhileDeadError();
  2185. return;
  2186. end
  2187. -- If the store-frame is open, we don't let people open up any other panels (just as if it were full-screened)
  2188. if ( StoreFrame_IsShown and StoreFrame_IsShown() ) then
  2189. self:ShowUIPanelFailed(frame);
  2190. return;
  2191. end
  2192. -- If we have a full-screen frame open, ignore other non-fullscreen open requests
  2193. if ( self:GetUIPanel("fullscreen") and (frameArea ~= "full") ) then
  2194. if ( force ) then
  2195. self:SetUIPanel("fullscreen", nil, 1);
  2196. else
  2197. self:ShowUIPanelFailed(frame);
  2198. return;
  2199. end
  2200. end
  2201. if ( GetUIPanelWindowInfo(frame, "checkFit") == 1 ) then
  2202. self:UpdateScaleForFit(frame);
  2203. end
  2204. -- If we have a "center" frame open, only listen to other "center" open requests
  2205. local centerFrame = self:GetUIPanel("center");
  2206. local centerArea, centerPushable;
  2207. if ( centerFrame ) then
  2208. if ( GetUIPanelWindowInfo(centerFrame, "allowOtherPanels") ) then
  2209. HideUIPanel(centerFrame);
  2210. centerFrame = nil;
  2211. else
  2212. centerArea = GetUIPanelWindowInfo(centerFrame, "area");
  2213. if ( centerArea and (centerArea == "center") and (frameArea ~= "center") and (frameArea ~= "full") ) then
  2214. if ( force ) then
  2215. self:SetUIPanel("center", nil, 1);
  2216. else
  2217. self:ShowUIPanelFailed(frame);
  2218. return;
  2219. end
  2220. end
  2221. centerPushable = GetUIPanelWindowInfo(centerFrame, "pushable") or 0;
  2222. end
  2223. end
  2224. -- Full-screen frames just replace each other
  2225. if ( frameArea == "full" ) then
  2226. securecall("CloseAllWindows");
  2227. self:SetUIPanel("fullscreen", frame);
  2228. return;
  2229. end
  2230. -- Native "center" frames just replace each other, and they take priority over pushed frames
  2231. if ( frameArea == "center" ) then
  2232. securecall("CloseWindows");
  2233. if ( not GetUIPanelWindowInfo(frame, "allowOtherPanels") ) then
  2234. securecall("CloseAllBags");
  2235. end
  2236. self:SetUIPanel("center", frame, 1);
  2237. return;
  2238. end
  2239. -- Doublewide frames take up the left and center spots
  2240. if ( frameArea == "doublewide" ) then
  2241. local leftFrame = self:GetUIPanel("left");
  2242. if ( leftFrame ) then
  2243. local leftPushable = GetUIPanelWindowInfo(leftFrame, "pushable") or 0;
  2244. if ( leftPushable > 0 and CanShowRightUIPanel(leftFrame) ) then
  2245. -- Push left to right
  2246. self:MoveUIPanel("left", "right", UIPANEL_SKIP_SET_POINT);
  2247. elseif ( centerFrame and CanShowRightUIPanel(centerFrame) ) then
  2248. self:MoveUIPanel("center", "right", UIPANEL_SKIP_SET_POINT);
  2249. end
  2250. end
  2251. self:SetUIPanel("doublewide", frame);
  2252. return;
  2253. end
  2254. -- If not pushable, close any doublewide frames
  2255. local doublewideFrame = self:GetUIPanel("doublewide");
  2256. if ( doublewideFrame ) then
  2257. if ( framePushable == 0 ) then
  2258. -- Set as left (closes doublewide) and slide over the right frame
  2259. self:SetUIPanel("left", frame, 1);
  2260. self:MoveUIPanel("right", "center");
  2261. elseif ( CanShowRightUIPanel(frame) ) then
  2262. -- Set as right
  2263. self:SetUIPanel("right", frame);
  2264. else
  2265. self:SetUIPanel("left", frame);
  2266. end
  2267. return;
  2268. end
  2269. -- Try to put it on the left
  2270. local leftFrame = self:GetUIPanel("left");
  2271. if ( not leftFrame ) then
  2272. self:SetUIPanel("left", frame);
  2273. return;
  2274. end
  2275. local leftPushable = GetUIPanelWindowInfo(leftFrame, "pushable") or 0;
  2276. -- Two open already
  2277. local rightFrame = self:GetUIPanel("right");
  2278. if ( centerFrame and not rightFrame ) then
  2279. -- If not pushable and left isn't pushable
  2280. if ( leftPushable == 0 and framePushable == 0 ) then
  2281. -- Replace left
  2282. self:SetUIPanel("left", frame);
  2283. elseif ( ( framePushable > centerPushable or centerArea == "center" ) and CanShowRightUIPanel(frame) ) then
  2284. -- This one is highest priority, show as right
  2285. self:SetUIPanel("right", frame);
  2286. elseif ( framePushable < leftPushable ) then
  2287. if ( centerArea == "center" ) then
  2288. if ( CanShowRightUIPanel(leftFrame) ) then
  2289. -- Skip center
  2290. self:MoveUIPanel("left", "right", UIPANEL_SKIP_SET_POINT);
  2291. self:SetUIPanel("left", frame);
  2292. else
  2293. -- Replace left
  2294. self:SetUIPanel("left", frame);
  2295. end
  2296. else
  2297. if ( CanShowUIPanels(frame, leftFrame, centerFrame) ) then
  2298. -- Shift both
  2299. self:MoveUIPanel("center", "right", UIPANEL_SKIP_SET_POINT);
  2300. self:MoveUIPanel("left", "center", UIPANEL_SKIP_SET_POINT);
  2301. self:SetUIPanel("left", frame);
  2302. else
  2303. -- Replace left
  2304. self:SetUIPanel("left", frame);
  2305. end
  2306. end
  2307. elseif ( framePushable <= centerPushable and centerArea ~= "center" and CanShowUIPanels(leftFrame, frame, centerFrame) ) then
  2308. -- Push center
  2309. self:MoveUIPanel("center", "right", UIPANEL_SKIP_SET_POINT);
  2310. self:SetUIPanel("center", frame);
  2311. elseif ( framePushable <= centerPushable and centerArea ~= "center" ) then
  2312. -- Replace left
  2313. self:SetUIPanel("left", frame);
  2314. else
  2315. -- Replace center
  2316. self:SetUIPanel("center", frame);
  2317. end
  2318. return;
  2319. end
  2320. -- If there's only one open...
  2321. if ( not centerFrame ) then
  2322. -- If neither is pushable, replace
  2323. if ( (leftPushable == 0) and (framePushable == 0) ) then
  2324. self:SetUIPanel("left", frame);
  2325. return;
  2326. end
  2327. -- Highest priority goes to center
  2328. if ( leftPushable > framePushable ) then
  2329. self:MoveUIPanel("left", "center", UIPANEL_SKIP_SET_POINT);
  2330. self:SetUIPanel("left", frame);
  2331. else
  2332. self:SetUIPanel("center", frame);
  2333. end
  2334. return;
  2335. end
  2336. -- Three are shown
  2337. local rightPushable = GetUIPanelWindowInfo(rightFrame, "pushable") or 0;
  2338. if ( framePushable > rightPushable ) then
  2339. -- This one is highest priority, slide the other two over
  2340. if ( CanShowUIPanels(centerFrame, rightFrame, frame) ) then
  2341. self:MoveUIPanel("center", "left", UIPANEL_SKIP_SET_POINT);
  2342. self:MoveUIPanel("right", "center", UIPANEL_SKIP_SET_POINT);
  2343. self:SetUIPanel("right", frame);
  2344. else
  2345. self:MoveUIPanel("right", "left", UIPANEL_SKIP_SET_POINT);
  2346. self:SetUIPanel("center", frame);
  2347. end
  2348. elseif ( framePushable > centerPushable ) then
  2349. -- This one is middle priority, so move the center frame to the left
  2350. self:MoveUIPanel("center", "left", UIPANEL_SKIP_SET_POINT);
  2351. self:SetUIPanel("center", frame);
  2352. else
  2353. self:SetUIPanel("left", frame);
  2354. end
  2355. end
  2356. function FramePositionDelegate:ShowUIPanelFailed(frame)
  2357. if GetUIPanelWindowInfo(frame, "showFailedFunc") then
  2358. frame:ExecuteAttribute("UIPanelLayout-showFailedFunc");
  2359. end
  2360. end
  2361. function FramePositionDelegate:SetUIPanel(key, frame, skipSetPoint)
  2362. if ( key == "fullscreen" ) then
  2363. local oldFrame = self.fullscreen;
  2364. self.fullscreen = frame;
  2365. if ( oldFrame ) then
  2366. oldFrame:Hide();
  2367. end
  2368. if ( frame ) then
  2369. UIParent:Hide();
  2370. frame:Show();
  2371. else
  2372. UIParent:Show();
  2373. SetUIVisibility(true);
  2374. end
  2375. return;
  2376. elseif ( key == "doublewide" ) then
  2377. local oldLeft = self.left;
  2378. local oldCenter = self.center;
  2379. local oldDoubleWide = self.doublewide;
  2380. self.doublewide = frame;
  2381. self.left = nil;
  2382. self.center = nil;
  2383. if ( oldDoubleWide ) then
  2384. oldDoubleWide:Hide();
  2385. end
  2386. if ( oldLeft ) then
  2387. oldLeft:Hide();
  2388. end
  2389. if ( oldCenter ) then
  2390. oldCenter:Hide();
  2391. end
  2392. elseif ( key ~= "left" and key ~= "center" and key ~= "right" ) then
  2393. return;
  2394. else
  2395. local oldFrame = self[key];
  2396. self[key] = frame;
  2397. if ( oldFrame ) then
  2398. oldFrame:Hide();
  2399. else
  2400. if ( self.doublewide ) then
  2401. if ( key == "left" or key == "center" ) then
  2402. self.doublewide:Hide();
  2403. self.doublewide = nil;
  2404. end
  2405. end
  2406. end
  2407. end
  2408. if ( not skipSetPoint ) then
  2409. securecall("UpdateUIPanelPositions", frame);
  2410. end
  2411. if ( frame ) then
  2412. frame:Show();
  2413. -- Hide all child windows
  2414. securecall("CloseChildWindows");
  2415. end
  2416. end
  2417. function FramePositionDelegate:MoveUIPanel(current, new, skipSetPoint, skipOperationUnlessCurrentIsValid)
  2418. if ( current ~= "left" and current ~= "center" and current ~= "right" and new ~= "left" and new ~= "center" and new ~= "right" ) then
  2419. return;
  2420. end
  2421. if skipOperationUnlessCurrentIsValid and not self[current] then
  2422. return;
  2423. end
  2424. self:SetUIPanel(new, nil, skipSetPoint);
  2425. if ( self[current] ) then
  2426. self[current]:Raise();
  2427. self[new] = self[current];
  2428. self[current] = nil;
  2429. if ( not skipSetPoint ) then
  2430. securecall("UpdateUIPanelPositions", self[new]);
  2431. end
  2432. end
  2433. end
  2434. function FramePositionDelegate:HideUIPanel(frame, skipSetPoint)
  2435. -- If we're hiding the full-screen frame, just hide it
  2436. if ( frame == self:GetUIPanel("fullscreen") ) then
  2437. self:SetUIPanel("fullscreen", nil);
  2438. return;
  2439. end
  2440. -- If we're hiding the right frame, just hide it
  2441. if ( frame == self:GetUIPanel("right") ) then
  2442. self:SetUIPanel("right", nil, skipSetPoint);
  2443. return;
  2444. elseif ( frame == self:GetUIPanel("doublewide") ) then
  2445. -- Slide over any right frame (hides the doublewide)
  2446. self:MoveUIPanel("right", "left", skipSetPoint);
  2447. return;
  2448. end
  2449. -- If we're hiding the center frame, slide over any right frame
  2450. local centerFrame = self:GetUIPanel("center");
  2451. if ( frame == centerFrame ) then
  2452. self:MoveUIPanel("right", "center", skipSetPoint);
  2453. elseif ( frame == self:GetUIPanel("left") ) then
  2454. -- If we're hiding the left frame, move the other frames left, unless the center is a native center frame
  2455. if ( centerFrame ) then
  2456. local area = GetUIPanelWindowInfo(centerFrame, "area");
  2457. if ( area ) then
  2458. if ( area == "center" ) then
  2459. -- Slide left, skip the center
  2460. self:MoveUIPanel("right", "left", skipSetPoint);
  2461. return;
  2462. else
  2463. -- Slide everything left
  2464. self:MoveUIPanel("center", "left", UIPANEL_SKIP_SET_POINT);
  2465. self:MoveUIPanel("right", "center", skipSetPoint);
  2466. return;
  2467. end
  2468. end
  2469. end
  2470. self:SetUIPanel("left", nil, skipSetPoint);
  2471. else
  2472. frame:Hide();
  2473. end
  2474. end
  2475. function FramePositionDelegate:GetUIPanel(key)
  2476. if ( key ~= "left" and key ~= "center" and key ~= "right" and key ~= "doublewide" and key ~= "fullscreen" ) then
  2477. return nil;
  2478. end
  2479. return self[key];
  2480. end
  2481. function FramePositionDelegate:UpdateUIPanelPositions(currentFrame)
  2482. if ( self.updatingPanels ) then
  2483. return;
  2484. end
  2485. self.updatingPanels = true;
  2486. local topOffset = UIParent:GetAttribute("TOP_OFFSET");
  2487. local leftOffset = UIParent:GetAttribute("LEFT_OFFSET");
  2488. local centerOffset = UIParent:GetAttribute("CENTER_OFFSET");
  2489. local rightOffset = UIParent:GetAttribute("RIGHT_OFFSET");
  2490. local xSpacing = UIParent:GetAttribute("PANEl_SPACING_X");
  2491. local info;
  2492. local frame = self:GetUIPanel("left");
  2493. if ( frame ) then
  2494. local xOff = GetUIPanelWindowInfo(frame,"xoffset") or 0;
  2495. local yOff = GetUIPanelWindowInfo(frame,"yoffset") or 0;
  2496. local bottomClampOverride = GetUIPanelWindowInfo(frame,"bottomClampOverride");
  2497. local minYOffset = GetUIPanelWindowInfo(frame,"minYOffset");
  2498. local yPos = ClampUIPanelY(frame, yOff + topOffset, minYOffset, bottomClampOverride);
  2499. frame:ClearAllPoints();
  2500. frame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", leftOffset + xOff, yPos);
  2501. centerOffset = leftOffset + GetUIPanelWidth(frame) + xOff;
  2502. UIParent:SetAttribute("CENTER_OFFSET", centerOffset);
  2503. frame:Raise();
  2504. else
  2505. centerOffset = leftOffset;
  2506. UIParent:SetAttribute("CENTER_OFFSET", centerOffset);
  2507. frame = self:GetUIPanel("doublewide");
  2508. if ( frame ) then
  2509. local xOff = GetUIPanelWindowInfo(frame,"xoffset") or 0;
  2510. local yOff = GetUIPanelWindowInfo(frame,"yoffset") or 0;
  2511. local bottomClampOverride = GetUIPanelWindowInfo(frame,"bottomClampOverride");
  2512. local minYOffset = GetUIPanelWindowInfo(frame,"minYOffset");
  2513. local yPos = ClampUIPanelY(frame, yOff + topOffset, minYOffset, bottomClampOverride);
  2514. frame:ClearAllPoints();
  2515. frame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", leftOffset + xOff, yPos);
  2516. rightOffset = leftOffset + GetUIPanelWidth(frame) + xOff;
  2517. UIParent:SetAttribute("RIGHT_OFFSET", rightOffset);
  2518. frame:Raise();
  2519. end
  2520. end
  2521. frame = self:GetUIPanel("center");
  2522. if ( frame ) then
  2523. if ( CanShowCenterUIPanel(frame) ) then
  2524. local area = GetUIPanelWindowInfo(frame, "area");
  2525. local xOff = GetUIPanelWindowInfo(frame,"xoffset") or 0;
  2526. local yOff = GetUIPanelWindowInfo(frame,"yoffset") or 0;
  2527. local bottomClampOverride = GetUIPanelWindowInfo(frame,"bottomClampOverride");
  2528. local minYOffset = GetUIPanelWindowInfo(frame,"minYOffset");
  2529. local yPos = ClampUIPanelY(frame, yOff + topOffset, minYOffset, bottomClampOverride);
  2530. if ( area ~= "center" ) then
  2531. frame:ClearAllPoints();
  2532. xOff = xOff + xSpacing; -- add separating space
  2533. frame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", centerOffset + xOff, yPos);
  2534. end
  2535. rightOffset = centerOffset + GetUIPanelWidth(frame) + xOff;
  2536. else
  2537. if ( frame == currentFrame ) then
  2538. frame = self:GetUIPanel("left") or self:GetUIPanel("doublewide");
  2539. if ( frame ) then
  2540. self:HideUIPanel(frame);
  2541. self.updatingPanels = nil;
  2542. self:UpdateUIPanelPositions(currentFrame);
  2543. return;
  2544. end
  2545. end
  2546. self:SetUIPanel("center", nil, 1);
  2547. rightOffset = centerOffset + UIParent:GetAttribute("DEFAULT_FRAME_WIDTH");
  2548. end
  2549. frame:Raise();
  2550. elseif ( not self:GetUIPanel("doublewide") ) then
  2551. if ( self:GetUIPanel("left") ) then
  2552. rightOffset = centerOffset + UIParent:GetAttribute("DEFAULT_FRAME_WIDTH");
  2553. else
  2554. rightOffset = leftOffset + UIParent:GetAttribute("DEFAULT_FRAME_WIDTH") * 2
  2555. end
  2556. end
  2557. UIParent:SetAttribute("RIGHT_OFFSET", rightOffset);
  2558. frame = self:GetUIPanel("right");
  2559. if ( frame ) then
  2560. if ( CanShowRightUIPanel(frame) ) then
  2561. local xOff = GetUIPanelWindowInfo(frame,"xoffset") or 0;
  2562. local yOff = GetUIPanelWindowInfo(frame,"yoffset") or 0;
  2563. local bottomClampOverride = GetUIPanelWindowInfo(frame,"bottomClampOverride");
  2564. local minYOffset = GetUIPanelWindowInfo(frame,"minYOffset");
  2565. local yPos = ClampUIPanelY(frame, yOff + topOffset, minYOffset, bottomClampOverride);
  2566. xOff = xOff + xSpacing; -- add separating space
  2567. frame:ClearAllPoints();
  2568. frame:SetPoint("TOPLEFT", "UIParent", "TOPLEFT", rightOffset + xOff, yPos);
  2569. else
  2570. if ( frame == currentFrame ) then
  2571. frame = GetUIPanel("center") or GetUIPanel("left") or GetUIPanel("doublewide");
  2572. if ( frame ) then
  2573. self:HideUIPanel(frame);
  2574. self.updatingPanels = nil;
  2575. self:UpdateUIPanelPositions(currentFrame);
  2576. return;
  2577. end
  2578. end
  2579. self:SetUIPanel("right", nil, 1);
  2580. end
  2581. frame:Raise();
  2582. end
  2583. if ( currentFrame and GetUIPanelWindowInfo(currentFrame, "checkFit") == 1 ) then
  2584. self:UpdateScaleForFit(currentFrame);
  2585. end
  2586. self.updatingPanels = nil;
  2587. end
  2588. function FramePositionDelegate:UpdateScaleForFit(frame)
  2589. local horizRatio = UIParent:GetWidth() / GetUIPanelWidth(frame);
  2590. local vertRatio = UIParent:GetHeight() / GetUIPanelHeight(frame);
  2591. if ( horizRatio < 1 or vertRatio < 1 ) then
  2592. frame:SetScale(min(horizRatio, vertRatio));
  2593. else
  2594. frame:SetScale(1);
  2595. end
  2596. end
  2597. function FramePositionDelegate:UIParentManageFramePositions()
  2598. UIPARENT_VARIABLE_OFFSETS["rightActionBarsX"] = VerticalMultiBarsContainer:GetWidth();
  2599. -- Update the variable with the happy magic number.
  2600. UpdateMenuBarTop();
  2601. -- Frames that affect offsets in y axis
  2602. local yOffsetFrames = {};
  2603. -- Frames that affect offsets in x axis
  2604. local xOffsetFrames = {};
  2605. -- Set up flags
  2606. local hasBottomLeft, hasBottomRight, hasPetBar;
  2607. if ( not PlayerPowerBarAlt:IsUserPlaced() ) then
  2608. local barInfo = GetUnitPowerBarInfo(PlayerPowerBarAlt.unit);
  2609. if ( PlayerPowerBarAlt:IsShown() and barInfo and barInfo.anchorTop ) then
  2610. PlayerPowerBarAlt:ClearAllPoints();
  2611. UIPARENT_MANAGED_FRAME_POSITIONS["PlayerPowerBarAlt"] = UIPARENT_ALTERNATE_FRAME_POSITIONS["PlayerPowerBarAlt_Top"];
  2612. else
  2613. PlayerPowerBarAlt:ClearAllPoints();
  2614. UIPARENT_MANAGED_FRAME_POSITIONS["PlayerPowerBarAlt"] = UIPARENT_ALTERNATE_FRAME_POSITIONS["PlayerPowerBarAlt_Bottom"];
  2615. end
  2616. end
  2617. if ( OverrideActionBar and OverrideActionBar:IsShown() ) then
  2618. tinsert(yOffsetFrames, "overrideActionBar");
  2619. elseif ( PetBattleFrame and PetBattleFrame:IsShown() ) then
  2620. tinsert(yOffsetFrames, "petBattleFrame");
  2621. else
  2622. if ( MultiBarBottomLeft:IsShown() or MultiBarBottomRight:IsShown() ) then
  2623. tinsert(yOffsetFrames, "bottomEither");
  2624. end
  2625. if ( MultiBarBottomRight:IsShown() ) then
  2626. tinsert(yOffsetFrames, "bottomRight");
  2627. hasBottomRight = 1;
  2628. end
  2629. if ( MultiBarBottomLeft:IsShown() ) then
  2630. tinsert(yOffsetFrames, "bottomLeft");
  2631. hasBottomLeft = 1;
  2632. end
  2633. -- TODO: Leaving this here for now since ChatFrame2 references it. Do we still need ChatFrame2 to be managed?
  2634. if ( MultiBarRight:IsShown() ) then
  2635. tinsert(xOffsetFrames, "rightRight");
  2636. end
  2637. if ( MultiBarRight:IsShown() ) then
  2638. tinsert(xOffsetFrames, "rightActionBarsX");
  2639. end
  2640. if (PetActionBarFrame_IsAboveStance and PetActionBarFrame_IsAboveStance()) then
  2641. tinsert(yOffsetFrames, "justBottomRightAndStance");
  2642. end
  2643. if ( ( PetActionBarFrame and PetActionBarFrame:IsShown() ) or ( StanceBarFrame and StanceBarFrame:IsShown() ) or
  2644. ( MultiCastActionBarFrame and MultiCastActionBarFrame:IsShown() ) or ( PossessBarFrame and PossessBarFrame:IsShown() ) or
  2645. ( MainMenuBarVehicleLeaveButton and MainMenuBarVehicleLeaveButton:IsShown() ) ) then
  2646. tinsert(yOffsetFrames, "pet");
  2647. hasPetBar = 1;
  2648. end
  2649. if ( TutorialFrameAlertButton:IsShown() ) then
  2650. tinsert(yOffsetFrames, "tutorialAlert");
  2651. end
  2652. if ( PlayerPowerBarAlt:IsShown() and not PlayerPowerBarAlt:IsUserPlaced() ) then
  2653. local barInfo = GetUnitPowerBarInfo(PlayerPowerBarAlt.unit);
  2654. if ( not barInfo or not barInfo.anchorTop ) then
  2655. tinsert(yOffsetFrames, "playerPowerBarAlt");
  2656. end
  2657. end
  2658. if UIWidgetPowerBarContainerFrame and UIWidgetPowerBarContainerFrame:GetNumWidgetsShowing() > 0 then
  2659. tinsert(yOffsetFrames, "powerBarWidgets");
  2660. end
  2661. if (ExtraActionBarFrame and ExtraActionBarFrame:IsShown() ) then
  2662. tinsert(yOffsetFrames, "extraActionBarFrame");
  2663. end
  2664. if (ZoneAbilityFrame and ZoneAbilityFrame:IsShown()) then
  2665. tinsert(yOffsetFrames, "ZoneAbilityFrame");
  2666. end
  2667. if ( TalkingHeadFrame and TalkingHeadFrame:IsShown() ) then
  2668. tinsert(yOffsetFrames, "talkingHeadFrame");
  2669. end
  2670. if ( ClassResourceOverlayParentFrame and ClassResourceOverlayParentFrame:IsShown() ) then
  2671. tinsert(yOffsetFrames, "classResourceOverlayFrame");
  2672. tinsert(yOffsetFrames, "classResourceOverlayOffset");
  2673. end
  2674. if ( CastingBarFrame and not CastingBarFrame:GetAttribute("ignoreFramePositionManager") ) then
  2675. tinsert(yOffsetFrames, "castingBar");
  2676. end
  2677. end
  2678. if ( menuBarTop == 55 ) then
  2679. UIPARENT_MANAGED_FRAME_POSITIONS["TutorialFrameAlertButton"].yOffset = -10;
  2680. else
  2681. UIPARENT_MANAGED_FRAME_POSITIONS["TutorialFrameAlertButton"].yOffset = -30;
  2682. end
  2683. -- Iterate through frames and set anchors according to the flags set
  2684. for index, value in pairs(UIPARENT_MANAGED_FRAME_POSITIONS) do
  2685. if ( value.playerPowerBarAlt and PlayerPowerBarAlt and not PlayerPowerBarAlt:IsUserPlaced()) then
  2686. value.playerPowerBarAlt = PlayerPowerBarAlt:GetHeight() + 10;
  2687. end
  2688. if ( value.powerBarWidgets and UIWidgetPowerBarContainerFrame ) then
  2689. value.powerBarWidgets = UIWidgetPowerBarContainerFrame:GetHeight() + 10;
  2690. end
  2691. if ( value.extraActionBarFrame and ExtraActionBarFrame ) then
  2692. value.extraActionBarFrame = ExtraActionBarFrame:GetHeight() + 10;
  2693. end
  2694. if ( value.ZoneAbilityFrame and ZoneAbilityFrame ) then
  2695. value.ZoneAbilityFrame = ZoneAbilityFrame:GetHeight() + 10;
  2696. end
  2697. if ( value.bonusActionBar and BonusActionBarFrame ) then
  2698. value.bonusActionBar = BonusActionBarFrame:GetHeight() - MainMenuBar:GetHeight();
  2699. end
  2700. if ( value.castingBar ) then
  2701. value.castingBar = CastingBarFrame:GetHeight() + 14;
  2702. end
  2703. if ( value.talkingHeadFrame and TalkingHeadFrame and TalkingHeadFrame:IsShown() ) then
  2704. value.talkingHeadFrame = TalkingHeadFrame:GetHeight() - 10;
  2705. end
  2706. if ( ClassResourceOverlayParentFrame and ClassResourceOverlayParentFrame:IsShown() ) then
  2707. if ( value.classResourceOverlayFrame ) then
  2708. value.classResourceOverlayFrame = ClassResourceOverlayParentFrame:GetHeight() + 10;
  2709. end
  2710. if ( value.classResourceOverlayOffset ) then
  2711. value.classResourceOverlayOffset = -20;
  2712. end
  2713. end
  2714. securecall("UIParent_ManageFramePosition", index, value, yOffsetFrames, xOffsetFrames, hasBottomLeft, hasBottomRight, hasPetBar);
  2715. end
  2716. -- Custom positioning not handled by the loop
  2717. -- MainMenuBar
  2718. if not MainMenuBar:IsUserPlaced() and not MicroButtonAndBagsBar:IsUserPlaced() then
  2719. local screenWidth = UIParent:GetWidth();
  2720. local barScale = 1;
  2721. local barWidth = MainMenuBar:GetWidth();
  2722. local barMargin = MAIN_MENU_BAR_MARGIN;
  2723. local bagsWidth = MicroButtonAndBagsBar:GetWidth();
  2724. local contentsWidth = barWidth + bagsWidth;
  2725. if contentsWidth > screenWidth then
  2726. barScale = screenWidth / contentsWidth;
  2727. barWidth = barWidth * barScale;
  2728. bagsWidth = bagsWidth * barScale;
  2729. barMargin = barMargin * barScale;
  2730. end
  2731. MainMenuBar:SetScale(barScale);
  2732. MainMenuBar:ClearAllPoints();
  2733. -- if there's no overlap with between action bar and bag bar while it's in the center, use center anchor
  2734. local roomLeft = screenWidth - barWidth - barMargin * 2;
  2735. if roomLeft >= bagsWidth * 2 then
  2736. MainMenuBar:SetPoint("BOTTOM", UIParent, 0, MainMenuBar:GetYOffset());
  2737. else
  2738. local xOffset = 0;
  2739. -- if both bars can fit without overlap, move the action bar to the left
  2740. -- otherwise sacrifice the art for more room
  2741. if roomLeft >= bagsWidth then
  2742. xOffset = roomLeft - bagsWidth + barMargin;
  2743. else
  2744. xOffset = math.max((roomLeft - bagsWidth) / 2 + barMargin, 0);
  2745. end
  2746. MainMenuBar:SetPoint("BOTTOMLEFT", UIParent, xOffset / barScale, MainMenuBar:GetYOffset());
  2747. end
  2748. end
  2749. -- Update Stance bar appearance
  2750. if ( MultiBarBottomLeft:IsShown() ) then
  2751. SlidingActionBarTexture0:Hide();
  2752. SlidingActionBarTexture1:Hide();
  2753. if ( StanceBarFrame ) then
  2754. StanceBarLeft:Hide();
  2755. StanceBarRight:Hide();
  2756. StanceBarMiddle:Hide();
  2757. for i=1, NUM_STANCE_SLOTS do
  2758. _G["StanceButton"..i]:GetNormalTexture():SetWidth(52);
  2759. _G["StanceButton"..i]:GetNormalTexture():SetHeight(52);
  2760. end
  2761. end
  2762. else
  2763. if (PetActionBarFrame_IsAboveStance and PetActionBarFrame_IsAboveStance()) then
  2764. SlidingActionBarTexture0:Hide();
  2765. SlidingActionBarTexture1:Hide();
  2766. else
  2767. SlidingActionBarTexture0:Show();
  2768. SlidingActionBarTexture1:Show();
  2769. end
  2770. if ( StanceBarFrame ) then
  2771. if ( GetNumShapeshiftForms() > 2 ) then
  2772. StanceBarMiddle:Show();
  2773. end
  2774. StanceBarLeft:Show();
  2775. StanceBarRight:Show();
  2776. for i=1, NUM_STANCE_SLOTS do
  2777. _G["StanceButton"..i]:GetNormalTexture():SetWidth(64);
  2778. _G["StanceButton"..i]:GetNormalTexture():SetHeight(64);
  2779. end
  2780. end
  2781. end
  2782. -- HACK: we have too many bars in this game now...
  2783. -- if the Stance bar is shown then hide the multi-cast bar
  2784. -- we'll have to figure out what we should do in this case if it ever really becomes a problem
  2785. -- HACK 2: if the possession bar is shown then hide the multi-cast bar
  2786. -- yeah, way too many bars...
  2787. if ( ( StanceBarFrame and StanceBarFrame:IsShown() ) or
  2788. ( PossessBarFrame and PossessBarFrame:IsShown() ) ) then
  2789. HideMultiCastActionBar();
  2790. elseif ( HasMultiCastActionBar and HasMultiCastActionBar() ) then
  2791. ShowMultiCastActionBar();
  2792. end
  2793. -- If petactionbar is already shown, set its point in addition to changing its y target
  2794. if ( PetActionBarFrame:IsShown() ) then
  2795. PetActionBar_UpdatePositionValues();
  2796. PetActionBarFrame:SetPoint("TOPLEFT", MainMenuBar, "BOTTOMLEFT", PETACTIONBAR_XPOS, PETACTIONBAR_YPOS);
  2797. end
  2798. -- Set battlefield minimap position
  2799. if ( BattlefieldMapTab and not BattlefieldMapTab:IsUserPlaced() ) then
  2800. BattlefieldMapTab:SetPoint("BOTTOMLEFT", "UIParent", "BOTTOMRIGHT", -BATTLEFIELD_MAP_WIDTH-CONTAINER_OFFSET_X, BATTLEFIELD_TAB_OFFSET_Y);
  2801. end
  2802. -- Setup y anchors
  2803. local anchorY = 0
  2804. local buffsAnchorY = min(0, (MINIMAP_BOTTOM_EDGE_EXTENT or 0) - BuffFrame.bottomEdgeExtent);
  2805. -- Count right action bars
  2806. local rightActionBars = 0;
  2807. if ( IsNormalActionBarState() ) then
  2808. if ( SHOW_MULTI_ACTIONBAR_3 ) then
  2809. rightActionBars = 1;
  2810. if ( SHOW_MULTI_ACTIONBAR_4 ) then
  2811. rightActionBars = 2;
  2812. end
  2813. end
  2814. end
  2815. -- BelowMinimap Widgets - need to move below buffs/debuffs if at least 1 right action bar is showing
  2816. if UIWidgetBelowMinimapContainerFrame and UIWidgetBelowMinimapContainerFrame:GetNumWidgetsShowing() > 0 then
  2817. if rightActionBars > 0 then
  2818. anchorY = min(anchorY, buffsAnchorY);
  2819. end
  2820. UIWidgetBelowMinimapContainerFrame:ClearAllPoints();
  2821. UIWidgetBelowMinimapContainerFrame:SetPoint("TOPRIGHT", MinimapCluster, "BOTTOMRIGHT", -CONTAINER_OFFSET_X, anchorY);
  2822. anchorY = anchorY - UIWidgetBelowMinimapContainerFrame:GetHeight() - 4;
  2823. end
  2824. --Setup Vehicle seat indicator offset - needs to move below buffs/debuffs if both right action bars are showing
  2825. if ( VehicleSeatIndicator and VehicleSeatIndicator:IsShown() ) then
  2826. if ( rightActionBars == 2 ) then
  2827. anchorY = min(anchorY, buffsAnchorY);
  2828. VehicleSeatIndicator:SetPoint("TOPRIGHT", MinimapCluster, "BOTTOMRIGHT", -100, anchorY);
  2829. elseif ( rightActionBars == 1 ) then
  2830. VehicleSeatIndicator:SetPoint("TOPRIGHT", MinimapCluster, "BOTTOMRIGHT", -62, anchorY);
  2831. else
  2832. VehicleSeatIndicator:SetPoint("TOPRIGHT", MinimapCluster, "BOTTOMRIGHT", 0, anchorY);
  2833. end
  2834. anchorY = anchorY - VehicleSeatIndicator:GetHeight() - 4; --The -4 is there to give a small buffer for things like the QuestTimeFrame below the Seat Indicator
  2835. end
  2836. -- Boss frames - need to move below buffs/debuffs if both right action bars are showing
  2837. local numBossFrames = 0;
  2838. for i = 1, MAX_BOSS_FRAMES do
  2839. if ( _G["Boss"..i.."TargetFrame"]:IsShown() ) then
  2840. numBossFrames = i;
  2841. end
  2842. end
  2843. if ( numBossFrames > 0 ) then
  2844. if ( rightActionBars > 1 ) then
  2845. anchorY = min(anchorY, buffsAnchorY);
  2846. end
  2847. Boss1TargetFrame:SetPoint("TOPRIGHT", "MinimapCluster", "BOTTOMRIGHT", -(CONTAINER_OFFSET_X * 1.3) + 60, anchorY * 1.333); -- by 1.333 because it's 0.75 scale
  2848. anchorY = anchorY - (numBossFrames * (68 + BOSS_FRAME_CASTBAR_HEIGHT) + BOSS_FRAME_CASTBAR_HEIGHT);
  2849. end
  2850. -- Setup durability offset
  2851. if ( DurabilityFrame ) then
  2852. DurabilityFrame:SetPoint("TOPRIGHT", "MinimapCluster", "BOTTOMRIGHT", -CONTAINER_OFFSET_X, anchorY);
  2853. if ( DurabilityFrame:IsShown() ) then
  2854. anchorY = anchorY - DurabilityFrame:GetHeight();
  2855. end
  2856. end
  2857. if ( ArenaEnemyFrames ) then
  2858. ArenaEnemyFrames:ClearAllPoints();
  2859. ArenaEnemyFrames:SetPoint("TOPRIGHT", MinimapCluster, "BOTTOMRIGHT", -CONTAINER_OFFSET_X, anchorY);
  2860. end
  2861. if ( ArenaPrepFrames ) then
  2862. ArenaPrepFrames:ClearAllPoints();
  2863. ArenaPrepFrames:SetPoint("TOPRIGHT", MinimapCluster, "BOTTOMRIGHT", -CONTAINER_OFFSET_X, anchorY);
  2864. end
  2865. -- ObjectiveTracker - needs to move below buffs/debuffs if at least 1 right action bar is showing
  2866. if ( rightActionBars > 0 ) then
  2867. anchorY = min(anchorY, buffsAnchorY);
  2868. end
  2869. if ( ObjectiveTrackerFrame and not ObjectiveTrackerFrame:IsUserPlaced() ) then
  2870. local numArenaOpponents = GetNumArenaOpponents();
  2871. if ( ArenaEnemyFrames and ArenaEnemyFrames:IsShown() and (numArenaOpponents > 0) ) then
  2872. ObjectiveTrackerFrame:ClearAllPoints();
  2873. ObjectiveTrackerFrame:SetPoint("TOPRIGHT", ArenaEnemyFrames_GetBestAnchorUnitFrameForOppponent(numArenaOpponents), "BOTTOMRIGHT", 2, -35);
  2874. elseif ( ArenaPrepFrames and ArenaPrepFrames:IsShown() and (numArenaOpponents > 0) ) then
  2875. ObjectiveTrackerFrame:ClearAllPoints();
  2876. ObjectiveTrackerFrame:SetPoint("TOPRIGHT", ArenaPrepFrames_GetBestAnchorUnitFrameForOppponent(numArenaOpponents), "BOTTOMRIGHT", 2, -35);
  2877. else
  2878. -- We're using Simple Quest Tracking, automagically size and position!
  2879. ObjectiveTrackerFrame:ClearAllPoints();
  2880. -- move up if only the minimap cluster is above, move down a little otherwise
  2881. ObjectiveTrackerFrame:SetPoint("TOPRIGHT", "MinimapCluster", "BOTTOMRIGHT", -OBJTRACKER_OFFSET_X, anchorY);
  2882. end
  2883. ObjectiveTrackerFrame:SetPoint("BOTTOMRIGHT", "UIParent", "BOTTOMRIGHT", -OBJTRACKER_OFFSET_X, CONTAINER_OFFSET_Y);
  2884. end
  2885. -- Update chat dock since the dock could have moved
  2886. FCF_DockUpdate();
  2887. UpdateContainerFrameAnchors();
  2888. end
  2889. -- Call this function to update the positions of all frames that can appear on the right side of the screen
  2890. function UIParent_ManageFramePositions()
  2891. --Dispatch to secure code
  2892. FramePositionDelegate:SetAttribute("uiparent-manage", true);
  2893. end
  2894. function ToggleFrame(frame)
  2895. if ( frame:IsShown() ) then
  2896. HideUIPanel(frame);
  2897. else
  2898. ShowUIPanel(frame);
  2899. end
  2900. end
  2901. -- We keep direct references to protect against replacement.
  2902. local InCombatLockdown = InCombatLockdown;
  2903. local issecure = issecure;
  2904. -- We no longer allow addons to show or hide UI panels in combat.
  2905. local function CheckProtectedFunctionsAllowed()
  2906. if ( InCombatLockdown() and not issecure() ) then
  2907. DisplayInterfaceActionBlockedMessage();
  2908. return false;
  2909. end
  2910. return true;
  2911. end
  2912. function ShowUIPanel(frame, force)
  2913. if ( not frame or frame:IsShown() ) then
  2914. return;
  2915. end
  2916. if ( not CheckProtectedFunctionsAllowed() ) then
  2917. return;
  2918. end
  2919. if ( not GetUIPanelWindowInfo(frame, "area") ) then
  2920. frame:Show();
  2921. return;
  2922. end
  2923. -- Dispatch to secure code
  2924. FramePositionDelegate:SetAttribute("panel-force", force);
  2925. FramePositionDelegate:SetAttribute("panel-frame", frame);
  2926. FramePositionDelegate:SetAttribute("panel-show", true);
  2927. end
  2928. function HideUIPanel(frame, skipSetPoint)
  2929. if ( not frame or not frame:IsShown() ) then
  2930. return;
  2931. end
  2932. if ( not CheckProtectedFunctionsAllowed() ) then
  2933. return;
  2934. end
  2935. if ( not GetUIPanelWindowInfo(frame, "area") ) then
  2936. frame:Hide();
  2937. return;
  2938. end
  2939. --Dispatch to secure code
  2940. FramePositionDelegate:SetAttribute("panel-frame", frame);
  2941. FramePositionDelegate:SetAttribute("panel-skipSetPoint", skipSetPoint);
  2942. FramePositionDelegate:SetAttribute("panel-hide", true);
  2943. end
  2944. function ShowOptionsPanel(optionsFrame, lastFrame, categoryToSelect)
  2945. -- NOTE: Toggle isn't currently necessary because showing an options panel hides everything else.
  2946. ShowUIPanel(optionsFrame);
  2947. optionsFrame.lastFrame = lastFrame;
  2948. if categoryToSelect then
  2949. OptionsFrame_OpenToCategory(optionsFrame, categoryToSelect);
  2950. end
  2951. end
  2952. function GetUIPanel(key)
  2953. return FramePositionDelegate:GetUIPanel(key);
  2954. end
  2955. function GetUIPanelWidth(frame)
  2956. return GetUIPanelWindowInfo(frame, "width") or frame:GetWidth() + (GetUIPanelWindowInfo(frame, "extraWidth") or 0);
  2957. end
  2958. function GetUIPanelHeight(frame)
  2959. return GetUIPanelWindowInfo(frame, "height") or frame:GetHeight() + (GetUIPanelWindowInfo(frame, "extraHeight") or 0);
  2960. end
  2961. --Allow a bit of overlap because there are built-in transparencies and buffers already
  2962. local MINIMAP_OVERLAP_ALLOWED = 60;
  2963. function GetMaxUIPanelsWidth()
  2964. --[[ local bufferBoundry = UIParent:GetRight() - UIParent:GetAttribute("RIGHT_OFFSET_BUFFER");
  2965. if ( Minimap:IsShown() and not MinimapCluster:IsUserPlaced() ) then
  2966. -- If the Minimap is in the default place, make sure you wont overlap it either
  2967. return min(MinimapCluster:GetLeft()+MINIMAP_OVERLAP_ALLOWED, bufferBoundry);
  2968. else
  2969. -- If the minimap has been moved, make sure not to overlap the right side bars
  2970. return bufferBoundry;
  2971. end
  2972. ]]
  2973. return UIParent:GetRight() - UIParent:GetAttribute("RIGHT_OFFSET_BUFFER");
  2974. end
  2975. function ClampUIPanelY(frame, yOffset, minYOffset, bottomClampOverride)
  2976. local bottomPos = UIParent:GetTop() + yOffset - GetUIPanelHeight(frame);
  2977. local bottomClamp = bottomClampOverride or 140;
  2978. if (bottomPos < bottomClamp) then
  2979. yOffset = yOffset + (bottomClamp - bottomPos);
  2980. end
  2981. if (yOffset > -10) then
  2982. yOffset = minYOffset or -10;
  2983. end
  2984. return yOffset;
  2985. end
  2986. function CanShowRightUIPanel(frame)
  2987. local width = frame and GetUIPanelWidth(frame) or UIParent:GetAttribute("DEFAULT_FRAME_WIDTH");
  2988. local rightSide = UIParent:GetAttribute("RIGHT_OFFSET") + width;
  2989. return rightSide < GetMaxUIPanelsWidth();
  2990. end
  2991. function CanShowCenterUIPanel(frame)
  2992. local width = frame and GetUIPanelWidth(frame) or UIParent:GetAttribute("DEFAULT_FRAME_WIDTH");
  2993. local rightSide = UIParent:GetAttribute("CENTER_OFFSET") + width;
  2994. return rightSide < GetMaxUIPanelsWidth();
  2995. end
  2996. function CanShowUIPanels(leftFrame, centerFrame, rightFrame)
  2997. local offset = UIParent:GetAttribute("LEFT_OFFSET");
  2998. if ( leftFrame ) then
  2999. offset = offset + GetUIPanelWidth(leftFrame);
  3000. if ( centerFrame ) then
  3001. local area = GetUIPanelWindowInfo(centerFrame, "area");
  3002. if ( area ~= "center" ) then
  3003. offset = offset + ( GetUIPanelWindowInfo(centerFrame, "width") or UIParent:GetAttribute("DEFAULT_FRAME_WIDTH") );
  3004. else
  3005. offset = offset + GetUIPanelWidth(centerFrame);
  3006. end
  3007. if ( rightFrame ) then
  3008. offset = offset + GetUIPanelWidth(rightFrame);
  3009. end
  3010. end
  3011. elseif ( centerFrame ) then
  3012. offset = GetUIPanelWidth(centerFrame);
  3013. end
  3014. if ( offset < GetMaxUIPanelsWidth() ) then
  3015. return 1;
  3016. end
  3017. end
  3018. function CanOpenPanels()
  3019. --[[
  3020. if ( UnitIsDead("player") ) then
  3021. return nil;
  3022. end
  3023. Previously couldn't open frames if player was out of control i.e. feared
  3024. if ( UnitIsDead("player") or UIParent.isOutOfControl ) then
  3025. return nil;
  3026. end
  3027. ]]
  3028. local centerFrame = GetUIPanel("center");
  3029. if ( not centerFrame ) then
  3030. return 1;
  3031. end
  3032. local area = GetUIPanelWindowInfo(centerFrame, "area");
  3033. local allowOtherPanels = GetUIPanelWindowInfo(centerFrame, "allowOtherPanels");
  3034. if ( area and (area == "center") and not allowOtherPanels ) then
  3035. return nil;
  3036. end
  3037. return 1;
  3038. end
  3039. -- this function handles possibly tainted values and so
  3040. -- should always be called from secure code using securecall()
  3041. function CloseChildWindows()
  3042. local childWindow;
  3043. for index, value in pairs(UIChildWindows) do
  3044. childWindow = _G[value];
  3045. if ( childWindow ) then
  3046. childWindow:Hide();
  3047. end
  3048. end
  3049. end
  3050. -- this function handles possibly tainted values and so
  3051. -- should always be called from secure code using securecall()
  3052. function CloseSpecialWindows()
  3053. local found;
  3054. for index, value in pairs(UISpecialFrames) do
  3055. local frame = _G[value];
  3056. if ( frame and frame:IsShown() ) then
  3057. frame:Hide();
  3058. found = 1;
  3059. end
  3060. end
  3061. return found;
  3062. end
  3063. function CloseWindows(ignoreCenter, frameToIgnore)
  3064. -- This function will close all frames that are not the current frame
  3065. local leftFrame = GetUIPanel("left");
  3066. local centerFrame = GetUIPanel("center");
  3067. local rightFrame = GetUIPanel("right");
  3068. local doublewideFrame = GetUIPanel("doublewide");
  3069. local fullScreenFrame = GetUIPanel("fullscreen");
  3070. local found = leftFrame or centerFrame or rightFrame or doublewideFrame or fullScreenFrame;
  3071. if ( not frameToIgnore or frameToIgnore ~= leftFrame ) then
  3072. HideUIPanel(leftFrame, UIPANEL_SKIP_SET_POINT);
  3073. end
  3074. HideUIPanel(fullScreenFrame, UIPANEL_SKIP_SET_POINT);
  3075. HideUIPanel(doublewideFrame, UIPANEL_SKIP_SET_POINT);
  3076. if ( not frameToIgnore or frameToIgnore ~= centerFrame ) then
  3077. if ( centerFrame ) then
  3078. local area = GetUIPanelWindowInfo(centerFrame, "area");
  3079. if ( area ~= "center" or not ignoreCenter ) then
  3080. HideUIPanel(centerFrame, UIPANEL_SKIP_SET_POINT);
  3081. end
  3082. end
  3083. end
  3084. if ( not frameToIgnore or frameToIgnore ~= rightFrame ) then
  3085. if ( rightFrame ) then
  3086. HideUIPanel(rightFrame, UIPANEL_SKIP_SET_POINT);
  3087. end
  3088. end
  3089. found = securecall("CloseSpecialWindows") or found;
  3090. UpdateUIPanelPositions();
  3091. return found;
  3092. end
  3093. function CloseAllWindows_WithExceptions()
  3094. -- When the player loses control we close all UIs, unless they're handled below
  3095. local centerFrame = GetUIPanel("center");
  3096. local ignoreCenter = (centerFrame and GetUIPanelWindowInfo(centerFrame, "ignoreControlLost")) or IsOptionFrameOpen();
  3097. CloseAllWindows(ignoreCenter);
  3098. end
  3099. function CloseAllWindows(ignoreCenter)
  3100. local bagsVisible = nil;
  3101. local windowsVisible = nil;
  3102. for i=1, NUM_CONTAINER_FRAMES, 1 do
  3103. local containerFrame = _G["ContainerFrame"..i];
  3104. if ( containerFrame:IsShown() ) then
  3105. containerFrame:Hide();
  3106. bagsVisible = 1;
  3107. end
  3108. end
  3109. windowsVisible = CloseWindows(ignoreCenter);
  3110. return (bagsVisible or windowsVisible);
  3111. end
  3112. -- this function handles possibly tainted values and so
  3113. -- should always be called from secure code using securecall()
  3114. function CloseMenus()
  3115. local menusVisible = nil;
  3116. local menu
  3117. for index, value in pairs(UIMenus) do
  3118. menu = _G[value];
  3119. if ( menu and menu:IsShown() ) then
  3120. menu:Hide();
  3121. menusVisible = 1;
  3122. end
  3123. end
  3124. return menusVisible;
  3125. end
  3126. function UpdateUIPanelPositions(currentFrame)
  3127. FramePositionDelegate:SetAttribute("panel-frame", currentFrame)
  3128. FramePositionDelegate:SetAttribute("panel-update", true);
  3129. end
  3130. function MaximizeUIPanel(currentFrame, maximizePoint)
  3131. FramePositionDelegate:SetAttribute("panel-frame", currentFrame)
  3132. FramePositionDelegate:SetAttribute("panel-maximize", true);
  3133. end
  3134. function RestoreUIPanelArea(currentFrame)
  3135. FramePositionDelegate:SetAttribute("panel-frame", currentFrame)
  3136. FramePositionDelegate:SetAttribute("panel-restore", true);
  3137. end
  3138. function IsOptionFrameOpen()
  3139. if ( GameMenuFrame:IsShown() or InterfaceOptionsFrame:IsShown() or (KeyBindingFrame and KeyBindingFrame:IsShown()) ) then
  3140. return 1;
  3141. else
  3142. return nil;
  3143. end
  3144. end
  3145. function LowerFrameLevel(frame)
  3146. frame:SetFrameLevel(frame:GetFrameLevel()-1);
  3147. end
  3148. function RaiseFrameLevel(frame)
  3149. frame:SetFrameLevel(frame:GetFrameLevel()+1);
  3150. end
  3151. function PassClickToParent(self, ...)
  3152. self:GetParent():Click(...);
  3153. end
  3154. -- Function to reposition frames if they get dragged off screen
  3155. function ValidateFramePosition(frame, offscreenPadding, returnOffscreen)
  3156. if ( not frame ) then
  3157. return;
  3158. end
  3159. local left = frame:GetLeft();
  3160. local right = frame:GetRight();
  3161. local top = frame:GetTop();
  3162. local bottom = frame:GetBottom();
  3163. local newAnchorX, newAnchorY;
  3164. if ( not offscreenPadding ) then
  3165. offscreenPadding = 15;
  3166. end
  3167. if ( bottom < (0 + MainMenuBar:GetHeight() + offscreenPadding)) then
  3168. -- Off the bottom of the screen
  3169. newAnchorY = MainMenuBar:GetHeight() + frame:GetHeight() - GetScreenHeight();
  3170. elseif ( top > GetScreenHeight() ) then
  3171. -- Off the top of the screen
  3172. newAnchorY = 0;
  3173. end
  3174. if ( left < 0 ) then
  3175. -- Off the left of the screen
  3176. newAnchorX = 0;
  3177. elseif ( right > GetScreenWidth() ) then
  3178. -- Off the right of the screen
  3179. newAnchorX = GetScreenWidth() - frame:GetWidth();
  3180. end
  3181. if ( newAnchorX or newAnchorY ) then
  3182. if ( returnOffscreen ) then
  3183. return 1;
  3184. else
  3185. if ( not newAnchorX ) then
  3186. newAnchorX = left;
  3187. elseif ( not newAnchorY ) then
  3188. newAnchorY = top - GetScreenHeight();
  3189. end
  3190. frame:ClearAllPoints();
  3191. frame:SetPoint("TOPLEFT", nil, "TOPLEFT", newAnchorX, newAnchorY);
  3192. end
  3193. else
  3194. if ( returnOffscreen ) then
  3195. return nil;
  3196. end
  3197. end
  3198. end
  3199. -- Time --
  3200. function RecentTimeDate(year, month, day, hour)
  3201. local lastOnline;
  3202. if ( (year == 0) or (year == nil) ) then
  3203. if ( (month == 0) or (month == nil) ) then
  3204. if ( (day == 0) or (day == nil) ) then
  3205. if ( (hour == 0) or (hour == nil) ) then
  3206. lastOnline = LASTONLINE_MINS;
  3207. else
  3208. lastOnline = format(LASTONLINE_HOURS, hour);
  3209. end
  3210. else
  3211. lastOnline = format(LASTONLINE_DAYS, day);
  3212. end
  3213. else
  3214. lastOnline = format(LASTONLINE_MONTHS, month);
  3215. end
  3216. else
  3217. lastOnline = format(LASTONLINE_YEARS, year);
  3218. end
  3219. return lastOnline;
  3220. end
  3221. -- Frame fading and flashing --
  3222. local frameFadeManager = CreateFrame("FRAME");
  3223. -- Generic fade function
  3224. function UIFrameFade(frame, fadeInfo)
  3225. if (not frame) then
  3226. return;
  3227. end
  3228. if ( not fadeInfo.mode ) then
  3229. fadeInfo.mode = "IN";
  3230. end
  3231. local alpha;
  3232. if ( fadeInfo.mode == "IN" ) then
  3233. if ( not fadeInfo.startAlpha ) then
  3234. fadeInfo.startAlpha = 0;
  3235. end
  3236. if ( not fadeInfo.endAlpha ) then
  3237. fadeInfo.endAlpha = 1.0;
  3238. end
  3239. alpha = 0;
  3240. elseif ( fadeInfo.mode == "OUT" ) then
  3241. if ( not fadeInfo.startAlpha ) then
  3242. fadeInfo.startAlpha = 1.0;
  3243. end
  3244. if ( not fadeInfo.endAlpha ) then
  3245. fadeInfo.endAlpha = 0;
  3246. end
  3247. alpha = 1.0;
  3248. end
  3249. frame:SetAlpha(fadeInfo.startAlpha);
  3250. frame.fadeInfo = fadeInfo;
  3251. frame:Show();
  3252. local index = 1;
  3253. while FADEFRAMES[index] do
  3254. -- If frame is already set to fade then return
  3255. if ( FADEFRAMES[index] == frame ) then
  3256. return;
  3257. end
  3258. index = index + 1;
  3259. end
  3260. tinsert(FADEFRAMES, frame);
  3261. frameFadeManager:SetScript("OnUpdate", UIFrameFade_OnUpdate);
  3262. end
  3263. -- Convenience function to do a simple fade in
  3264. function UIFrameFadeIn(frame, timeToFade, startAlpha, endAlpha)
  3265. local fadeInfo = {};
  3266. fadeInfo.mode = "IN";
  3267. fadeInfo.timeToFade = timeToFade;
  3268. fadeInfo.startAlpha = startAlpha;
  3269. fadeInfo.endAlpha = endAlpha;
  3270. UIFrameFade(frame, fadeInfo);
  3271. end
  3272. -- Convenience function to do a simple fade out
  3273. function UIFrameFadeOut(frame, timeToFade, startAlpha, endAlpha)
  3274. local fadeInfo = {};
  3275. fadeInfo.mode = "OUT";
  3276. fadeInfo.timeToFade = timeToFade;
  3277. fadeInfo.startAlpha = startAlpha;
  3278. fadeInfo.endAlpha = endAlpha;
  3279. UIFrameFade(frame, fadeInfo);
  3280. end
  3281. function UIFrameFadeRemoveFrame(frame)
  3282. tDeleteItem(FADEFRAMES, frame);
  3283. end
  3284. -- Function that actually performs the alpha change
  3285. --[[
  3286. Fading frame attribute listing
  3287. ============================================================
  3288. frame.timeToFade [Num] Time it takes to fade the frame in or out
  3289. frame.mode ["IN", "OUT"] Fade mode
  3290. frame.finishedFunc [func()] Function that is called when fading is finished
  3291. frame.finishedArg1 [ANYTHING] Argument to the finishedFunc
  3292. frame.finishedArg2 [ANYTHING] Argument to the finishedFunc
  3293. frame.finishedArg3 [ANYTHING] Argument to the finishedFunc
  3294. frame.finishedArg4 [ANYTHING] Argument to the finishedFunc
  3295. frame.fadeHoldTime [Num] Time to hold the faded state
  3296. ]]
  3297. function UIFrameFade_OnUpdate(self, elapsed)
  3298. local index = 1;
  3299. local frame, fadeInfo;
  3300. while FADEFRAMES[index] do
  3301. frame = FADEFRAMES[index];
  3302. fadeInfo = FADEFRAMES[index].fadeInfo;
  3303. -- Reset the timer if there isn't one, this is just an internal counter
  3304. if ( not fadeInfo.fadeTimer ) then
  3305. fadeInfo.fadeTimer = 0;
  3306. end
  3307. fadeInfo.fadeTimer = fadeInfo.fadeTimer + elapsed;
  3308. -- 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
  3309. if ( fadeInfo.fadeTimer < fadeInfo.timeToFade ) then
  3310. if ( fadeInfo.mode == "IN" ) then
  3311. frame:SetAlpha((fadeInfo.fadeTimer / fadeInfo.timeToFade) * (fadeInfo.endAlpha - fadeInfo.startAlpha) + fadeInfo.startAlpha);
  3312. elseif ( fadeInfo.mode == "OUT" ) then
  3313. frame:SetAlpha(((fadeInfo.timeToFade - fadeInfo.fadeTimer) / fadeInfo.timeToFade) * (fadeInfo.startAlpha - fadeInfo.endAlpha) + fadeInfo.endAlpha);
  3314. end
  3315. else
  3316. frame:SetAlpha(fadeInfo.endAlpha);
  3317. -- If there is a fadeHoldTime then wait until its passed to continue on
  3318. if ( fadeInfo.fadeHoldTime and fadeInfo.fadeHoldTime > 0 ) then
  3319. fadeInfo.fadeHoldTime = fadeInfo.fadeHoldTime - elapsed;
  3320. else
  3321. -- Complete the fade and call the finished function if there is one
  3322. UIFrameFadeRemoveFrame(frame);
  3323. if ( fadeInfo.finishedFunc ) then
  3324. fadeInfo.finishedFunc(fadeInfo.finishedArg1, fadeInfo.finishedArg2, fadeInfo.finishedArg3, fadeInfo.finishedArg4);
  3325. fadeInfo.finishedFunc = nil;
  3326. end
  3327. end
  3328. end
  3329. index = index + 1;
  3330. end
  3331. if ( #FADEFRAMES == 0 ) then
  3332. self:SetScript("OnUpdate", nil);
  3333. end
  3334. end
  3335. function UIFrameIsFading(frame)
  3336. for index, value in pairs(FADEFRAMES) do
  3337. if ( value == frame ) then
  3338. return 1;
  3339. end
  3340. end
  3341. return nil;
  3342. end
  3343. local frameFlashManager = CreateFrame("FRAME");
  3344. local UIFrameFlashTimers = {};
  3345. local UIFrameFlashTimerRefCount = {};
  3346. -- Function to start a frame flashing
  3347. function UIFrameFlash(frame, fadeInTime, fadeOutTime, flashDuration, showWhenDone, flashInHoldTime, flashOutHoldTime, syncId)
  3348. if ( frame ) then
  3349. local index = 1;
  3350. -- If frame is already set to flash then return
  3351. while FLASHFRAMES[index] do
  3352. if ( FLASHFRAMES[index] == frame ) then
  3353. return;
  3354. end
  3355. index = index + 1;
  3356. end
  3357. if (syncId) then
  3358. frame.syncId = syncId;
  3359. if (UIFrameFlashTimers[syncId] == nil) then
  3360. UIFrameFlashTimers[syncId] = 0;
  3361. UIFrameFlashTimerRefCount[syncId] = 0;
  3362. end
  3363. UIFrameFlashTimerRefCount[syncId] = UIFrameFlashTimerRefCount[syncId]+1;
  3364. else
  3365. frame.syncId = nil;
  3366. end
  3367. -- Time it takes to fade in a flashing frame
  3368. frame.fadeInTime = fadeInTime;
  3369. -- Time it takes to fade out a flashing frame
  3370. frame.fadeOutTime = fadeOutTime;
  3371. -- How long to keep the frame flashing, -1 means forever
  3372. frame.flashDuration = flashDuration;
  3373. -- Show the flashing frame when the fadeOutTime has passed
  3374. frame.showWhenDone = showWhenDone;
  3375. -- Internal timer
  3376. frame.flashTimer = 0;
  3377. -- How long to hold the faded in state
  3378. frame.flashInHoldTime = flashInHoldTime;
  3379. -- How long to hold the faded out state
  3380. frame.flashOutHoldTime = flashOutHoldTime;
  3381. tinsert(FLASHFRAMES, frame);
  3382. frameFlashManager:SetScript("OnUpdate", UIFrameFlash_OnUpdate);
  3383. end
  3384. end
  3385. -- Called every frame to update flashing frames
  3386. function UIFrameFlash_OnUpdate(self, elapsed)
  3387. local frame;
  3388. local index = #FLASHFRAMES;
  3389. -- Update timers for all synced frames
  3390. for syncId, timer in pairs(UIFrameFlashTimers) do
  3391. UIFrameFlashTimers[syncId] = timer + elapsed;
  3392. end
  3393. while FLASHFRAMES[index] do
  3394. frame = FLASHFRAMES[index];
  3395. frame.flashTimer = frame.flashTimer + elapsed;
  3396. if ( (frame.flashTimer > frame.flashDuration) and frame.flashDuration ~= -1 ) then
  3397. UIFrameFlashStop(frame);
  3398. else
  3399. local flashTime = frame.flashTimer;
  3400. local alpha;
  3401. if (frame.syncId) then
  3402. flashTime = UIFrameFlashTimers[frame.syncId];
  3403. end
  3404. flashTime = flashTime%(frame.fadeInTime+frame.fadeOutTime+(frame.flashInHoldTime or 0)+(frame.flashOutHoldTime or 0));
  3405. if (flashTime < frame.fadeInTime) then
  3406. alpha = flashTime/frame.fadeInTime;
  3407. elseif (flashTime < frame.fadeInTime+(frame.flashInHoldTime or 0)) then
  3408. alpha = 1;
  3409. elseif (flashTime < frame.fadeInTime+(frame.flashInHoldTime or 0)+frame.fadeOutTime) then
  3410. alpha = 1 - ((flashTime - frame.fadeInTime - (frame.flashInHoldTime or 0))/frame.fadeOutTime);
  3411. else
  3412. alpha = 0;
  3413. end
  3414. frame:SetAlpha(alpha);
  3415. frame:Show();
  3416. end
  3417. -- Loop in reverse so that removing frames is safe
  3418. index = index - 1;
  3419. end
  3420. if ( #FLASHFRAMES == 0 ) then
  3421. self:SetScript("OnUpdate", nil);
  3422. end
  3423. end
  3424. -- Function to see if a frame is already flashing
  3425. function UIFrameIsFlashing(frame)
  3426. for index, value in pairs(FLASHFRAMES) do
  3427. if ( value == frame ) then
  3428. return 1;
  3429. end
  3430. end
  3431. return nil;
  3432. end
  3433. -- Function to stop flashing
  3434. function UIFrameFlashStop(frame)
  3435. tDeleteItem(FLASHFRAMES, frame);
  3436. frame:SetAlpha(1.0);
  3437. frame.flashTimer = nil;
  3438. if (frame.syncId) then
  3439. UIFrameFlashTimerRefCount[frame.syncId] = UIFrameFlashTimerRefCount[frame.syncId]-1;
  3440. if (UIFrameFlashTimerRefCount[frame.syncId] == 0) then
  3441. UIFrameFlashTimers[frame.syncId] = nil;
  3442. UIFrameFlashTimerRefCount[frame.syncId] = nil;
  3443. end
  3444. frame.syncId = nil;
  3445. end
  3446. if ( frame.showWhenDone ) then
  3447. frame:Show();
  3448. else
  3449. frame:Hide();
  3450. end
  3451. end
  3452. -- Functions to handle button pulsing (Highlight, Unhighlight)
  3453. function SetButtonPulse(button, duration, pulseRate)
  3454. button.pulseDuration = pulseRate;
  3455. button.pulseTimeLeft = duration
  3456. -- pulseRate is actually seconds per pulse state
  3457. button.pulseRate = pulseRate;
  3458. button.pulseOn = 0;
  3459. tinsert(PULSEBUTTONS, button);
  3460. end
  3461. -- Update the button pulsing
  3462. function ButtonPulse_OnUpdate(elapsed)
  3463. for index, button in pairs(PULSEBUTTONS) do
  3464. if ( button.pulseTimeLeft > 0 ) then
  3465. if ( button.pulseDuration < 0 ) then
  3466. if ( button.pulseOn == 1 ) then
  3467. button:UnlockHighlight();
  3468. button.pulseOn = 0;
  3469. else
  3470. button:LockHighlight();
  3471. button.pulseOn = 1;
  3472. end
  3473. button.pulseDuration = button.pulseRate;
  3474. end
  3475. button.pulseDuration = button.pulseDuration - elapsed;
  3476. button.pulseTimeLeft = button.pulseTimeLeft - elapsed;
  3477. else
  3478. button:UnlockHighlight();
  3479. button.pulseOn = 0;
  3480. tDeleteItem(PULSEBUTTONS, button);
  3481. end
  3482. end
  3483. end
  3484. function ButtonPulse_StopPulse(button)
  3485. for index, pulseButton in pairs(PULSEBUTTONS) do
  3486. if ( pulseButton == button ) then
  3487. tDeleteItem(PULSEBUTTONS, button);
  3488. end
  3489. end
  3490. end
  3491. function UIDoFramesIntersect(frame1, frame2)
  3492. if ( ( frame1:GetLeft() < frame2:GetRight() ) and ( frame1:GetRight() > frame2:GetLeft() ) and
  3493. ( frame1:GetBottom() < frame2:GetTop() ) and ( frame1:GetTop() > frame2:GetBottom() ) ) then
  3494. return true;
  3495. else
  3496. return false;
  3497. end
  3498. end
  3499. -- Lua Helper functions --
  3500. function BuildListString(...)
  3501. local text = ...;
  3502. if ( not text ) then
  3503. return nil;
  3504. end
  3505. local string = text;
  3506. for i=2, select("#", ...) do
  3507. text = select(i, ...);
  3508. if ( text ) then
  3509. string = string..", "..text;
  3510. end
  3511. end
  3512. return string;
  3513. end
  3514. function BuildColoredListString(...)
  3515. if ( select("#", ...) == 0 ) then
  3516. return nil;
  3517. end
  3518. -- Takes input where odd items are the text and even items determine whether the arg should be colored or not
  3519. local text, normal = ...;
  3520. local string;
  3521. if ( normal ) then
  3522. string = text;
  3523. else
  3524. string = RED_FONT_COLOR_CODE..text..FONT_COLOR_CODE_CLOSE;
  3525. end
  3526. for i=3, select("#", ...), 2 do
  3527. text, normal = select(i, ...);
  3528. if ( normal ) then
  3529. -- If meets the condition
  3530. string = string..", "..text;
  3531. else
  3532. -- If doesn't meet the condition
  3533. string = string..", "..RED_FONT_COLOR_CODE..text..FONT_COLOR_CODE_CLOSE;
  3534. end
  3535. end
  3536. return string;
  3537. end
  3538. function BuildNewLineListString(...)
  3539. local text;
  3540. local index = 1;
  3541. for i=1, select("#", ...) do
  3542. text = select(i, ...);
  3543. index = index + 1;
  3544. if ( text ) then
  3545. break;
  3546. end
  3547. end
  3548. if ( not text ) then
  3549. return nil;
  3550. end
  3551. local string = text;
  3552. for i=index, select("#", ...) do
  3553. text = select(i, ...);
  3554. if ( text ) then
  3555. string = string.."\n"..text;
  3556. end
  3557. end
  3558. return string;
  3559. end
  3560. function BuildMultilineTooltip(globalStringName, tooltip, r, g, b)
  3561. if ( not tooltip ) then
  3562. tooltip = GameTooltip;
  3563. end
  3564. if ( not r ) then
  3565. r = 1.0;
  3566. g = 1.0;
  3567. b = 1.0;
  3568. end
  3569. local i = 1;
  3570. local string = _G[globalStringName..i];
  3571. while (string) do
  3572. tooltip:AddLine(string, "", r, g, b);
  3573. i = i + 1;
  3574. string = _G[globalStringName..i];
  3575. end
  3576. end
  3577. function GetScaledCursorPosition()
  3578. local uiScale = UIParent:GetEffectiveScale();
  3579. local x, y = GetCursorPosition();
  3580. return x / uiScale, y / uiScale;
  3581. end
  3582. function GetScaledCursorDelta()
  3583. local uiScale = _UIParentGetEffectiveScale(_UIParentRef);
  3584. local x, y = GetCursorDelta();
  3585. return x / uiScale, y / uiScale;
  3586. end
  3587. function MouseIsOver(region, topOffset, bottomOffset, leftOffset, rightOffset)
  3588. return region:IsMouseOver(topOffset, bottomOffset, leftOffset, rightOffset);
  3589. end
  3590. -- replace the C functions with local lua versions
  3591. function getglobal(varr)
  3592. return _G[varr];
  3593. end
  3594. function setglobal(varr,value)
  3595. _G[varr] = value;
  3596. end
  3597. -- Wrapper for the desaturation function
  3598. function SetDesaturation(texture, desaturation)
  3599. texture:SetDesaturated(desaturation);
  3600. end
  3601. function GetMaterialTextColors(material)
  3602. local textColor = MATERIAL_TEXT_COLOR_TABLE[material];
  3603. local titleColor = MATERIAL_TITLETEXT_COLOR_TABLE[material];
  3604. if ( not(textColor and titleColor) ) then
  3605. textColor = MATERIAL_TEXT_COLOR_TABLE["Default"];
  3606. titleColor = MATERIAL_TITLETEXT_COLOR_TABLE["Default"];
  3607. end
  3608. return textColor, titleColor;
  3609. end
  3610. function OrderHallMissionFrame_EscapePressed()
  3611. return OrderHallMissionFrame and OrderHallMissionFrame.EscapePressed and OrderHallMissionFrame:EscapePressed();
  3612. end
  3613. function OrderHallTalentFrame_EscapePressed()
  3614. return OrderHallTalentFrame and OrderHallTalentFrame.EscapePressed and OrderHallTalentFrame:EscapePressed();
  3615. end
  3616. function BFAMissionFrame_EscapePressed()
  3617. return BFAMissionFrame and BFAMissionFrame.EscapePressed and BFAMissionFrame:EscapePressed();
  3618. end
  3619. -- Function that handles the escape key functions
  3620. function ToggleGameMenu()
  3621. if ( not UIParent:IsShown() ) then
  3622. UIParent:Show();
  3623. SetUIVisibility(true);
  3624. elseif ( C_Commentator.IsSpectating() and IsFrameLockActive("COMMENTATOR_SPECTATING_MODE") ) then
  3625. PvPCommentator:SetFrameLock(false);
  3626. elseif ( ModelPreviewFrame:IsShown() ) then
  3627. ModelPreviewFrame:Hide();
  3628. elseif ( StoreFrame_EscapePressed and StoreFrame_EscapePressed() ) then
  3629. elseif ( WowTokenRedemptionFrame_EscapePressed and WowTokenRedemptionFrame_EscapePressed() ) then
  3630. elseif ( securecall("StaticPopup_EscapePressed") ) then
  3631. elseif ( GameMenuFrame:IsShown() ) then
  3632. PlaySound(SOUNDKIT.IG_MAINMENU_QUIT);
  3633. HideUIPanel(GameMenuFrame);
  3634. elseif ( HelpFrame:IsShown() ) then
  3635. ToggleHelpFrame();
  3636. elseif ( VideoOptionsFrame:IsShown() ) then
  3637. VideoOptionsFrameCancel:Click();
  3638. elseif ( AudioOptionsFrame:IsShown() ) then
  3639. AudioOptionsFrameCancel:Click();
  3640. elseif ( SocialBrowserFrame and SocialBrowserFrame:IsShown() ) then
  3641. SocialBrowserFrame:Hide();
  3642. elseif ( InterfaceOptionsFrame:IsShown() ) then
  3643. InterfaceOptionsFrameCancel:Click();
  3644. elseif ( SocialPostFrame and Social_IsShown() ) then
  3645. Social_SetShown(false);
  3646. elseif ( TimeManagerFrame and TimeManagerFrame:IsShown() ) then
  3647. TimeManagerFrameCloseButton:Click();
  3648. elseif ( MultiCastFlyoutFrame:IsShown() ) then
  3649. MultiCastFlyoutFrame_Hide(MultiCastFlyoutFrame, true);
  3650. elseif (SpellFlyout:IsShown() ) then
  3651. SpellFlyout:Hide();
  3652. elseif ( securecall("FCFDockOverflow_CloseLists") ) then
  3653. elseif ( securecall("CloseMenus") ) then
  3654. elseif ( CloseCalendarMenus and securecall("CloseCalendarMenus") ) then
  3655. elseif ( CloseGuildMenus and securecall("CloseGuildMenus") ) then
  3656. elseif ( GarrisonMissionFrame_ClearMouse and securecall("GarrisonMissionFrame_ClearMouse") ) then
  3657. elseif ( GarrisonMissionFrame and GarrisonMissionFrame.MissionTab and GarrisonMissionFrame.MissionTab.MissionPage and GarrisonMissionFrame.MissionTab.MissionPage:IsVisible() ) then
  3658. GarrisonMissionFrame.MissionTab.MissionPage.CloseButton:Click();
  3659. elseif ( GarrisonShipyardFrame_ClearMouse and securecall("GarrisonShipyardFrame_ClearMouse") ) then
  3660. elseif ( GarrisonShipyardFrame and GarrisonShipyardFrame.MissionTab and GarrisonShipyardFrame.MissionTab.MissionPage and GarrisonShipyardFrame.MissionTab.MissionPage:IsVisible() ) then
  3661. GarrisonShipyardFrame.MissionTab.MissionPage.CloseButton:Click();
  3662. elseif ( securecall("OrderHallMissionFrame_EscapePressed") ) then
  3663. elseif ( securecall("OrderHallTalentFrame_EscapePressed") ) then
  3664. elseif ( securecall("BFAMissionFrame_EscapePressed") ) then
  3665. elseif ( SpellStopCasting() ) then
  3666. elseif ( SpellStopTargeting() ) then
  3667. elseif ( securecall("CloseAllWindows") ) then
  3668. elseif ( LootFrame:IsShown() ) then
  3669. -- if we're here, LootFrame was opened under the mouse (cvar "lootUnderMouse") so it didn't get closed by CloseAllWindows
  3670. LootFrame:Hide();
  3671. elseif ( ClearTarget() and (not UnitIsCharmed("player")) ) then
  3672. elseif ( OpacityFrame:IsShown() ) then
  3673. OpacityFrame:Hide();
  3674. elseif ( SplashFrame:IsShown() ) then
  3675. SplashFrame_Close();
  3676. elseif ( ChallengesKeystoneFrame and ChallengesKeystoneFrame:IsShown() ) then
  3677. ChallengesKeystoneFrame:Hide();
  3678. else
  3679. PlaySound(SOUNDKIT.IG_MAINMENU_OPEN);
  3680. ShowUIPanel(GameMenuFrame);
  3681. end
  3682. end
  3683. -- Visual Misc --
  3684. function GetScreenHeightScale()
  3685. local screenHeight = 768;
  3686. return GetScreenHeight()/screenHeight;
  3687. end
  3688. function GetScreenWidthScale()
  3689. local screenWidth = 1024;
  3690. return GetScreenWidth()/screenWidth;
  3691. end
  3692. function ShowInspectCursor()
  3693. SetCursor("INSPECT_CURSOR");
  3694. end
  3695. -- Helper function to show the inspect cursor if the ctrl key is down
  3696. function CursorUpdate(self)
  3697. if ( IsModifiedClick("DRESSUP") and self.hasItem ) then
  3698. ShowInspectCursor();
  3699. else
  3700. ResetCursor();
  3701. end
  3702. end
  3703. function CursorOnUpdate(self)
  3704. if ( GameTooltip:IsOwned(self) ) then
  3705. CursorUpdate(self);
  3706. end
  3707. end
  3708. function AnimateTexCoords(texture, textureWidth, textureHeight, frameWidth, frameHeight, numFrames, elapsed, throttle)
  3709. if ( not texture.frame ) then
  3710. -- initialize everything
  3711. texture.frame = 1;
  3712. texture.throttle = throttle;
  3713. texture.numColumns = floor(textureWidth/frameWidth);
  3714. texture.numRows = floor(textureHeight/frameHeight);
  3715. texture.columnWidth = frameWidth/textureWidth;
  3716. texture.rowHeight = frameHeight/textureHeight;
  3717. end
  3718. local frame = texture.frame;
  3719. if ( not texture.throttle or texture.throttle > throttle ) then
  3720. local framesToAdvance = floor(texture.throttle / throttle);
  3721. while ( frame + framesToAdvance > numFrames ) do
  3722. frame = frame - numFrames;
  3723. end
  3724. frame = frame + framesToAdvance;
  3725. texture.throttle = 0;
  3726. local left = mod(frame-1, texture.numColumns)*texture.columnWidth;
  3727. local right = left + texture.columnWidth;
  3728. local bottom = ceil(frame/texture.numColumns)*texture.rowHeight;
  3729. local top = bottom - texture.rowHeight;
  3730. texture:SetTexCoord(left, right, top, bottom);
  3731. texture.frame = frame;
  3732. else
  3733. texture.throttle = texture.throttle + elapsed;
  3734. end
  3735. end
  3736. -- Bindings --
  3737. function GetBindingFromClick(input)
  3738. local fullInput = "";
  3739. -- MUST BE IN THIS ORDER (ALT, CTRL, SHIFT)
  3740. if ( IsAltKeyDown() ) then
  3741. fullInput = fullInput.."ALT-";
  3742. end
  3743. if ( IsControlKeyDown() ) then
  3744. fullInput = fullInput.."CTRL-"
  3745. end
  3746. if ( IsShiftKeyDown() ) then
  3747. fullInput = fullInput.."SHIFT-"
  3748. end
  3749. if ( input == "LeftButton" ) then
  3750. fullInput = fullInput.."BUTTON1";
  3751. elseif ( input == "RightButton" ) then
  3752. fullInput = fullInput.."BUTTON2";
  3753. elseif ( input == "MiddleButton" ) then
  3754. fullInput = fullInput.."BUTTON3";
  3755. elseif ( input == "Button4" ) then
  3756. fullInput = fullInput.."BUTTON4";
  3757. elseif ( input == "Button5" ) then
  3758. fullInput = fullInput.."BUTTON5";
  3759. elseif ( input == "Button6" ) then
  3760. fullInput = fullInput.."BUTTON6";
  3761. elseif ( input == "Button7" ) then
  3762. fullInput = fullInput.."BUTTON7";
  3763. elseif ( input == "Button8" ) then
  3764. fullInput = fullInput.."BUTTON8";
  3765. elseif ( input == "Button9" ) then
  3766. fullInput = fullInput.."BUTTON9";
  3767. elseif ( input == "Button10" ) then
  3768. fullInput = fullInput.."BUTTON10";
  3769. elseif ( input == "Button11" ) then
  3770. fullInput = fullInput.."BUTTON11";
  3771. elseif ( input == "Button12" ) then
  3772. fullInput = fullInput.."BUTTON12";
  3773. elseif ( input == "Button13" ) then
  3774. fullInput = fullInput.."BUTTON13";
  3775. elseif ( input == "Button14" ) then
  3776. fullInput = fullInput.."BUTTON14";
  3777. elseif ( input == "Button15" ) then
  3778. fullInput = fullInput.."BUTTON15";
  3779. elseif ( input == "Button16" ) then
  3780. fullInput = fullInput.."BUTTON16";
  3781. elseif ( input == "Button17" ) then
  3782. fullInput = fullInput.."BUTTON17";
  3783. elseif ( input == "Button18" ) then
  3784. fullInput = fullInput.."BUTTON18";
  3785. elseif ( input == "Button19" ) then
  3786. fullInput = fullInput.."BUTTON19";
  3787. elseif ( input == "Button20" ) then
  3788. fullInput = fullInput.."BUTTON20";
  3789. elseif ( input == "Button21" ) then
  3790. fullInput = fullInput.."BUTTON21";
  3791. elseif ( input == "Button22" ) then
  3792. fullInput = fullInput.."BUTTON22";
  3793. elseif ( input == "Button23" ) then
  3794. fullInput = fullInput.."BUTTON23";
  3795. elseif ( input == "Button24" ) then
  3796. fullInput = fullInput.."BUTTON24";
  3797. elseif ( input == "Button25" ) then
  3798. fullInput = fullInput.."BUTTON25";
  3799. elseif ( input == "Button26" ) then
  3800. fullInput = fullInput.."BUTTON26";
  3801. elseif ( input == "Button27" ) then
  3802. fullInput = fullInput.."BUTTON27";
  3803. elseif ( input == "Button28" ) then
  3804. fullInput = fullInput.."BUTTON28";
  3805. elseif ( input == "Button29" ) then
  3806. fullInput = fullInput.."BUTTON29";
  3807. elseif ( input == "Button30" ) then
  3808. fullInput = fullInput.."BUTTON30";
  3809. elseif ( input == "Button31" ) then
  3810. fullInput = fullInput.."BUTTON31";
  3811. else
  3812. fullInput = fullInput..input;
  3813. end
  3814. return GetBindingByKey(fullInput);
  3815. end
  3816. -- Game Logic --
  3817. function OnInviteToPartyConfirmation(name, willConvertToRaid, questSessionActive)
  3818. if questSessionActive then
  3819. QuestSessionManager:OnInviteToPartyConfirmation(name, willConvertToRaid);
  3820. elseif willConvertToRaid then
  3821. local dialog = StaticPopup_Show("CONVERT_TO_RAID");
  3822. if ( dialog ) then
  3823. dialog.data = name;
  3824. end
  3825. else
  3826. C_PartyInfo.ConfirmInviteUnit(name);
  3827. end
  3828. end
  3829. function GetSocialColoredName(displayName, guid)
  3830. local _, color, relationship = SocialQueueUtil_GetRelationshipInfo(guid);
  3831. if ( relationship ) then
  3832. return color..displayName..FONT_COLOR_CODE_CLOSE;
  3833. end
  3834. return displayName;
  3835. end
  3836. local function AllowAutoAcceptInviteConfirmation(isQuickJoin, isSelfRelationship)
  3837. return isQuickJoin and isSelfRelationship and GetCVarBool("autoAcceptQuickJoinRequests") and not C_QuestSession.Exists();
  3838. end
  3839. local function ShouldAutoAcceptInviteConfirmation(invite)
  3840. local confirmationType, name, guid, rolesInvalid, willConvertToRaid = GetInviteConfirmationInfo(invite);
  3841. local _, _, _, isQuickJoin, clubID = C_PartyInfo.GetInviteReferralInfo(invite);
  3842. local _, _, selfRelationship = SocialQueueUtil_GetRelationshipInfo(guid, name, clubID);
  3843. return AllowAutoAcceptInviteConfirmation(isQuickJoin, selfRelationship);
  3844. end
  3845. function UpdateInviteConfirmationDialogs()
  3846. local invite = GetNextPendingInviteConfirmation();
  3847. if invite then
  3848. HandlePendingInviteConfirmation(invite);
  3849. end
  3850. end
  3851. function HandlePendingInviteConfirmation(invite)
  3852. if C_QuestSession.HasJoined() then
  3853. HandlePendingInviteConfirmation_QuestSession(invite);
  3854. else
  3855. HandlePendingInviteConfirmation_StaticPopup(invite);
  3856. end
  3857. end
  3858. function HandlePendingInviteConfirmation_StaticPopup(invite)
  3859. if not StaticPopup_FindVisible("GROUP_INVITE_CONFIRMATION") then
  3860. if ShouldAutoAcceptInviteConfirmation(invite) then
  3861. RespondToInviteConfirmation(invite, true);
  3862. else
  3863. local text = CreatePendingInviteConfirmationText(invite);
  3864. StaticPopup_Show("GROUP_INVITE_CONFIRMATION", text, nil, invite);
  3865. end
  3866. end
  3867. end
  3868. function HandlePendingInviteConfirmation_QuestSession(invite)
  3869. -- Chances are that we never want to auto-accept in a quest session,
  3870. -- so always show the dialog.
  3871. local text = CreatePendingInviteConfirmationText(invite);
  3872. QuestSessionManager:ShowGroupInviteConfirmation(invite, text);
  3873. end
  3874. function CreatePendingInviteConfirmationText(invite)
  3875. local confirmationType, name, guid, rolesInvalid, willConvertToRaid = GetInviteConfirmationInfo(invite);
  3876. if confirmationType == LE_INVITE_CONFIRMATION_REQUEST then
  3877. return CreatePendingInviteConfirmationText_Request(invite, name, guid, rolesInvalid, willConvertToRaid);
  3878. elseif confirmationType == LE_INVITE_CONFIRMATION_SUGGEST then
  3879. return CreatePendingInviteConfirmationText_Suggest(invite, name, guid, rolesInvalid, willConvertToRaid);
  3880. else
  3881. return CreatePendingInviteConfirmationText_AppendWarnings("", invite, name, guid, rolesInvalid, willConvertToRaid);
  3882. end
  3883. end
  3884. function CreatePendingInviteConfirmationText_Request(invite, name, guid, rolesInvalid, willConvertToRaid)
  3885. local coloredName, coloredSuggesterName = CreatePendingInviteConfirmationNames(invite, name, guid, rolesInvalid, willConvertToRaid);
  3886. local suggesterGuid, _, relationship, isQuickJoin, clubId = C_PartyInfo.GetInviteReferralInfo(invite);
  3887. --If we ourselves have a relationship with this player, we'll just act as if they asked through us.
  3888. local _, _, selfRelationship = SocialQueueUtil_GetRelationshipInfo(guid, name, clubId);
  3889. local text;
  3890. if selfRelationship then
  3891. local clubLink = clubId and GetCommunityLink(clubId) or nil;
  3892. if ( clubLink and selfRelationship == "club" ) then
  3893. if isQuickJoin then
  3894. text = INVITE_CONFIRMATION_REQUEST_FROM_COMMUNITY_QUICKJOIN:format(coloredName, clubLink);
  3895. else
  3896. text = INVITE_CONFIRMATION_REQUEST_FROM_COMMUNITY:format(coloredName, clubLink);
  3897. end
  3898. elseif isQuickJoin then
  3899. text = INVITE_CONFIRMATION_REQUEST_QUICKJOIN:format(coloredName);
  3900. else
  3901. text = INVITE_CONFIRMATION_REQUEST:format(coloredName);
  3902. end
  3903. elseif suggesterGuid then
  3904. if relationship == Enum.PartyRequestJoinRelation.Friend then
  3905. text = (isQuickJoin and INVITE_CONFIRMATION_REQUEST_FRIEND_QUICKJOIN or INVITE_CONFIRMATION_REQUEST_FRIEND):format(coloredSuggesterName, coloredName);
  3906. elseif relationship == Enum.PartyRequestJoinRelation.Guild then
  3907. text = (isQuickJoin and INVITE_CONFIRMATION_REQUEST_GUILD_QUICKJOIN or INVITE_CONFIRMATION_REQUEST_GUILD):format(coloredSuggesterName, coloredName);
  3908. elseif relationship == Enum.PartyRequestJoinRelation.Club then
  3909. text = (isQuickJoin and INVITE_CONFIRMATION_REQUEST_COMMUNITY_QUICKJOIN or INVITE_CONFIRMATION_REQUEST_COMMUNITY):format(coloredSuggesterName, coloredName);
  3910. else
  3911. text = INVITE_CONFIRMATION_REQUEST:format(coloredName);
  3912. end
  3913. else
  3914. text = (isQuickJoin and INVITE_CONFIRMATION_REQUEST_QUICKJOIN or INVITE_CONFIRMATION_REQUEST):format(coloredName);
  3915. end
  3916. return CreatePendingInviteConfirmationText_AppendWarnings(text, invite, name, guid, rolesInvalid, willConvertToRaid);
  3917. end
  3918. function CreatePendingInviteConfirmationNames(invite, name, guid, rolesInvalid, willConvertToRaid)
  3919. local suggesterGuid, suggesterName, relationship, isQuickJoin, clubId = C_PartyInfo.GetInviteReferralInfo(invite);
  3920. --If we ourselves have a relationship with this player, we'll just act as if they asked through us.
  3921. local _, color, selfRelationship, playerLink = SocialQueueUtil_GetRelationshipInfo(guid, name, clubId);
  3922. name = (playerLink and isQuickJoin) and ("["..playerLink.."]") or name;
  3923. if selfRelationship or isQuickJoin then
  3924. name = color .. name .. FONT_COLOR_CODE_CLOSE;
  3925. end
  3926. if selfRelationship then
  3927. return name;
  3928. elseif suggesterGuid then
  3929. suggesterName = GetSocialColoredName(suggesterName, suggesterGuid);
  3930. if relationship == Enum.PartyRequestJoinRelation.Friend or relationship == Enum.PartyRequestJoinRelation.Guild or relationship == Enum.PartyRequestJoinRelation.Club then
  3931. return name, suggesterName;
  3932. else
  3933. return name;
  3934. end
  3935. else
  3936. return name;
  3937. end
  3938. end
  3939. function CreatePendingInviteConfirmationText_Suggest(invite, name, guid, rolesInvalid, willConvertToRaid)
  3940. local suggesterGuid, suggesterName, relationship, isQuickJoin = C_PartyInfo.GetInviteReferralInfo(invite);
  3941. suggesterName = GetSocialColoredName(suggesterName, suggesterGuid);
  3942. name = GetSocialColoredName(name, guid);
  3943. -- Only using a single string here, if somebody is suggesting a person to join the group, QuickJoin text doesn't apply.
  3944. local text = INVITE_CONFIRMATION_SUGGEST:format(suggesterName, name);
  3945. return CreatePendingInviteConfirmationText_AppendWarnings(text, invite, name, guid, rolesInvalid, willConvertToRaid)
  3946. end
  3947. function CreatePendingInviteConfirmationText_AppendWarnings(text, invite, name, guid, rolesInvalid, willConvertToRaid)
  3948. local warnings = CreatePendingInviteConfirmationText_GetWarnings(invite, name, guid, rolesInvalid, willConvertToRaid);
  3949. if warnings ~= "" then
  3950. if text ~= "" then
  3951. return text.."\n\n"..warnings;
  3952. else
  3953. return warnings;
  3954. end
  3955. end
  3956. return text;
  3957. end
  3958. function CreatePendingInviteConfirmationText_GetWarnings(invite, name, guid, rolesInvalid, willConvertToRaid)
  3959. local warnings = {};
  3960. local invalidQueues = C_PartyInfo.GetInviteConfirmationInvalidQueues(invite);
  3961. if invalidQueues and #invalidQueues > 0 then
  3962. if rolesInvalid then
  3963. table.insert(warnings, INSTANCE_UNAVAILABLE_OTHER_NO_VALID_ROLES:format(name));
  3964. end
  3965. table.insert(warnings, INVITE_CONFIRMATION_QUEUE_WARNING:format(name));
  3966. for i=1, #invalidQueues do
  3967. local queueName = SocialQueueUtil_GetQueueName(invalidQueues[i]);
  3968. table.insert(warnings, NORMAL_FONT_COLOR:WrapTextInColorCode(queueName));
  3969. end
  3970. end
  3971. if willConvertToRaid then
  3972. table.insert(warnings, RED_FONT_COLOR:WrapTextInColorCode(LFG_LIST_CONVERT_TO_RAID_WARNING));
  3973. end
  3974. return table.concat(warnings, "\n");
  3975. end
  3976. function UnitHasMana(unit)
  3977. if ( UnitPowerMax(unit, Enum.PowerType.Mana) > 0 ) then
  3978. return 1;
  3979. end
  3980. return nil;
  3981. end
  3982. function RaiseFrameLevelByTwo(frame)
  3983. -- We do this enough that it saves closures.
  3984. frame:SetFrameLevel(frame:GetFrameLevel()+2);
  3985. end
  3986. function ShowResurrectRequest(offerer)
  3987. if ( ResurrectHasSickness() ) then
  3988. StaticPopup_Show("RESURRECT", offerer);
  3989. elseif ( ResurrectHasTimer() ) then
  3990. StaticPopup_Show("RESURRECT_NO_SICKNESS", offerer);
  3991. else
  3992. StaticPopup_Show("RESURRECT_NO_TIMER", offerer);
  3993. end
  3994. end
  3995. function RefreshAuras(frame, unit, numAuras, suffix, checkCVar, showBuffs)
  3996. if ( showBuffs ) then
  3997. RefreshBuffs(frame, unit, numAuras, suffix, checkCVar);
  3998. else
  3999. RefreshDebuffs(frame, unit, numAuras, suffix, checkCVar);
  4000. end
  4001. end
  4002. function RefreshBuffs(frame, unit, numBuffs, suffix, checkCVar)
  4003. local frameName = frame:GetName();
  4004. frame.hasDispellable = nil;
  4005. numBuffs = numBuffs or MAX_PARTY_BUFFS;
  4006. suffix = suffix or "Buff";
  4007. local unitStatus, statusColor;
  4008. local debuffTotal = 0;
  4009. local filter = ( checkCVar and SHOW_CASTABLE_BUFFS == "1" and UnitCanAssist("player", unit) ) and "HELPFUL|RAID" or "HELPFUL";
  4010. local numFrames = 0;
  4011. AuraUtil.ForEachAura(unit, filter, numBuffs, function(...)
  4012. local name, icon, count, debuffType, duration, expirationTime = ...;
  4013. -- if we have an icon to show then proceed with setting up the aura
  4014. if ( icon ) then
  4015. numFrames = numFrames + 1;
  4016. local buffName = frameName..suffix..numFrames;
  4017. -- set the icon
  4018. local buffIcon = _G[buffName.."Icon"];
  4019. buffIcon:SetTexture(icon);
  4020. -- setup the cooldown
  4021. local coolDown = _G[buffName.."Cooldown"];
  4022. if ( coolDown ) then
  4023. CooldownFrame_Set(coolDown, expirationTime - duration, duration, true);
  4024. end
  4025. -- show the aura
  4026. _G[buffName]:Show();
  4027. end
  4028. return numFrames >= numBuffs;
  4029. end);
  4030. for i=numFrames + 1,numBuffs do
  4031. local buffName = frameName..suffix..i;
  4032. local frame = _G[buffName];
  4033. if frame then
  4034. frame:Hide();
  4035. else
  4036. break;
  4037. end
  4038. end
  4039. end
  4040. function RefreshDebuffs(frame, unit, numDebuffs, suffix, checkCVar)
  4041. local frameName = frame:GetName();
  4042. suffix = suffix or "Debuff";
  4043. local frameNameWithSuffix = frameName..suffix;
  4044. frame.hasDispellable = nil;
  4045. numDebuffs = numDebuffs or MAX_PARTY_DEBUFFS;
  4046. local unitStatus, statusColor;
  4047. local debuffTotal = 0;
  4048. local isEnemy = UnitCanAttack("player", unit);
  4049. local filter = ( checkCVar and SHOW_DISPELLABLE_DEBUFFS == "1" and UnitCanAssist("player", unit) ) and "HARMFUL|RAID" or "HARMFUL";
  4050. if strsub(unit, 1, 5) == "party" then
  4051. unitStatus = _G[frameName.."Status"];
  4052. end
  4053. AuraUtil.ForEachAura(unit, filter, numDebuffs, function(...)
  4054. local name, icon, count, debuffType, duration, expirationTime, caster = ...;
  4055. if ( icon and ( SHOW_CASTABLE_DEBUFFS == "0" or not isEnemy or caster == "player" ) ) then
  4056. debuffTotal = debuffTotal + 1;
  4057. local debuffName = frameNameWithSuffix..debuffTotal;
  4058. -- if we have an icon to show then proceed with setting up the aura
  4059. -- set the icon
  4060. local debuffIcon = _G[debuffName.."Icon"];
  4061. debuffIcon:SetTexture(icon);
  4062. -- setup the border
  4063. local debuffBorder = _G[debuffName.."Border"];
  4064. local debuffColor = DebuffTypeColor[debuffType] or DebuffTypeColor["none"];
  4065. debuffBorder:SetVertexColor(debuffColor.r, debuffColor.g, debuffColor.b);
  4066. -- record interesting data for the aura button
  4067. statusColor = debuffColor;
  4068. frame.hasDispellable = 1;
  4069. -- setup the cooldown
  4070. local coolDown = _G[debuffName.."Cooldown"];
  4071. if ( coolDown ) then
  4072. CooldownFrame_Set(coolDown, expirationTime - duration, duration, true);
  4073. end
  4074. -- show the aura
  4075. _G[debuffName]:Show();
  4076. end
  4077. return debuffTotal >= numDebuffs;
  4078. end);
  4079. for i=debuffTotal+1,numDebuffs do
  4080. local debuffName = frameNameWithSuffix..i;
  4081. _G[debuffName]:Hide();
  4082. end
  4083. frame.debuffTotal = debuffTotal;
  4084. -- Reset unitStatus overlay graphic timer
  4085. if ( frame.numDebuffs and debuffTotal >= frame.numDebuffs ) then
  4086. frame.debuffCountdown = 30;
  4087. end
  4088. if ( unitStatus and statusColor ) then
  4089. unitStatus:SetVertexColor(statusColor.r, statusColor.g, statusColor.b);
  4090. end
  4091. end
  4092. function GetQuestDifficultyColor(level, isScaling, optQuestID)
  4093. if optQuestID and C_QuestLog.IsQuestDisabledForSession(optQuestID) then
  4094. return QuestDifficultyColors["disabled"], QuestDifficultyHighlightColors["disabled"];
  4095. end
  4096. if (isScaling) then
  4097. return GetScalingQuestDifficultyColor(level);
  4098. end
  4099. return GetRelativeDifficultyColor(UnitEffectiveLevel("player"), level);
  4100. end
  4101. function GetCreatureDifficultyColor(level)
  4102. return GetRelativeDifficultyColor(UnitEffectiveLevel("player"), level);
  4103. end
  4104. --How difficult is this challenge for this unit?
  4105. function GetRelativeDifficultyColor(unitLevel, challengeLevel)
  4106. local levelDiff = challengeLevel - unitLevel;
  4107. local color;
  4108. if ( levelDiff >= 5 ) then
  4109. return QuestDifficultyColors["impossible"], QuestDifficultyHighlightColors["impossible"];
  4110. elseif ( levelDiff >= 3 ) then
  4111. return QuestDifficultyColors["verydifficult"], QuestDifficultyHighlightColors["verydifficult"];
  4112. elseif ( levelDiff >= -4 ) then
  4113. return QuestDifficultyColors["difficult"], QuestDifficultyHighlightColors["difficult"];
  4114. elseif ( -levelDiff <= GetQuestGreenRange() ) then
  4115. return QuestDifficultyColors["standard"], QuestDifficultyHighlightColors["standard"];
  4116. else
  4117. return QuestDifficultyColors["trivial"], QuestDifficultyHighlightColors["trivial"];
  4118. end
  4119. end
  4120. function GetScalingQuestDifficultyColor(questLevel)
  4121. local playerLevel = UnitEffectiveLevel("player");
  4122. local levelDiff = questLevel - playerLevel;
  4123. if ( levelDiff >= 5 ) then
  4124. return QuestDifficultyColors["impossible"], QuestDifficultyHighlightColors["impossible"];
  4125. elseif ( levelDiff >= 3 ) then
  4126. return QuestDifficultyColors["verydifficult"], QuestDifficultyHighlightColors["verydifficult"];
  4127. elseif ( levelDiff >= 0 ) then
  4128. return QuestDifficultyColors["difficult"], QuestDifficultyHighlightColors["difficult"];
  4129. elseif ( -levelDiff <= GetScalingQuestGreenRange() ) then
  4130. return QuestDifficultyColors["standard"], QuestDifficultyHighlightColors["standard"];
  4131. else
  4132. return QuestDifficultyColors["trivial"], QuestDifficultyHighlightColors["trivial"];
  4133. end
  4134. end
  4135. -- takes in a table with r, g, and b entries and converts it to a color string
  4136. function ConvertRGBtoColorString(color)
  4137. local colorString = "|cff";
  4138. local r = color.r * 255;
  4139. local g = color.g * 255;
  4140. local b = color.b * 255;
  4141. colorString = colorString..string.format("%2x%2x%2x", r, g, b);
  4142. return colorString;
  4143. end
  4144. function GetDungeonNameWithDifficulty(name, difficultyName)
  4145. name = name or "";
  4146. if ( difficultyName == "" ) then
  4147. name = NORMAL_FONT_COLOR_CODE..name..FONT_COLOR_CODE_CLOSE;
  4148. else
  4149. name = NORMAL_FONT_COLOR_CODE..format(DUNGEON_NAME_WITH_DIFFICULTY, name, difficultyName)..FONT_COLOR_CODE_CLOSE;
  4150. end
  4151. return name;
  4152. end
  4153. -- Animated shine stuff --
  4154. function AnimatedShine_Start(shine, r, g, b)
  4155. if ( not tContains(SHINES_TO_ANIMATE, shine) ) then
  4156. shine.timer = 0;
  4157. tinsert(SHINES_TO_ANIMATE, shine);
  4158. end
  4159. local shineName = shine:GetName();
  4160. _G[shineName.."Shine1"]:Show();
  4161. _G[shineName.."Shine2"]:Show();
  4162. _G[shineName.."Shine3"]:Show();
  4163. _G[shineName.."Shine4"]:Show();
  4164. if ( r ) then
  4165. _G[shineName.."Shine1"]:SetVertexColor(r, g, b);
  4166. _G[shineName.."Shine2"]:SetVertexColor(r, g, b);
  4167. _G[shineName.."Shine3"]:SetVertexColor(r, g, b);
  4168. _G[shineName.."Shine4"]:SetVertexColor(r, g, b);
  4169. end
  4170. end
  4171. function AnimatedShine_Stop(shine)
  4172. tDeleteItem(SHINES_TO_ANIMATE, shine);
  4173. local shineName = shine:GetName();
  4174. _G[shineName.."Shine1"]:Hide();
  4175. _G[shineName.."Shine2"]:Hide();
  4176. _G[shineName.."Shine3"]:Hide();
  4177. _G[shineName.."Shine4"]:Hide();
  4178. end
  4179. function AnimatedShine_OnUpdate(elapsed)
  4180. local shine1, shine2, shine3, shine4;
  4181. local speed = 2.5;
  4182. local parent, distance;
  4183. for index, value in pairs(SHINES_TO_ANIMATE) do
  4184. shine1 = _G[value:GetName().."Shine1"];
  4185. shine2 = _G[value:GetName().."Shine2"];
  4186. shine3 = _G[value:GetName().."Shine3"];
  4187. shine4 = _G[value:GetName().."Shine4"];
  4188. value.timer = value.timer+elapsed;
  4189. if ( value.timer > speed*4 ) then
  4190. value.timer = 0;
  4191. end
  4192. parent = _G[value:GetName().."Shine"];
  4193. distance = parent:GetWidth();
  4194. if ( value.timer <= speed ) then
  4195. shine1:SetPoint("CENTER", parent, "TOPLEFT", value.timer/speed*distance, 0);
  4196. shine2:SetPoint("CENTER", parent, "BOTTOMRIGHT", -value.timer/speed*distance, 0);
  4197. shine3:SetPoint("CENTER", parent, "TOPRIGHT", 0, -value.timer/speed*distance);
  4198. shine4:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, value.timer/speed*distance);
  4199. elseif ( value.timer <= speed*2 ) then
  4200. shine1:SetPoint("CENTER", parent, "TOPRIGHT", 0, -(value.timer-speed)/speed*distance);
  4201. shine2:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, (value.timer-speed)/speed*distance);
  4202. shine3:SetPoint("CENTER", parent, "BOTTOMRIGHT", -(value.timer-speed)/speed*distance, 0);
  4203. shine4:SetPoint("CENTER", parent, "TOPLEFT", (value.timer-speed)/speed*distance, 0);
  4204. elseif ( value.timer <= speed*3 ) then
  4205. shine1:SetPoint("CENTER", parent, "BOTTOMRIGHT", -(value.timer-speed*2)/speed*distance, 0);
  4206. shine2:SetPoint("CENTER", parent, "TOPLEFT", (value.timer-speed*2)/speed*distance, 0);
  4207. shine3:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, (value.timer-speed*2)/speed*distance);
  4208. shine4:SetPoint("CENTER", parent, "TOPRIGHT", 0, -(value.timer-speed*2)/speed*distance);
  4209. else
  4210. shine1:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, (value.timer-speed*3)/speed*distance);
  4211. shine2:SetPoint("CENTER", parent, "TOPRIGHT", 0, -(value.timer-speed*3)/speed*distance);
  4212. shine3:SetPoint("CENTER", parent, "TOPLEFT", (value.timer-speed*3)/speed*distance, 0);
  4213. shine4:SetPoint("CENTER", parent, "BOTTOMRIGHT", -(value.timer-speed*3)/speed*distance, 0);
  4214. end
  4215. end
  4216. end
  4217. -- Autocast shine stuff --
  4218. AUTOCAST_SHINE_R = .95;
  4219. AUTOCAST_SHINE_G = .95;
  4220. AUTOCAST_SHINE_B = .32;
  4221. AUTOCAST_SHINE_SPEEDS = { 2, 4, 6, 8 };
  4222. AUTOCAST_SHINE_TIMERS = { 0, 0, 0, 0 };
  4223. local AUTOCAST_SHINES = {};
  4224. function AutoCastShine_OnLoad(self)
  4225. self.sparkles = {};
  4226. local name = self:GetName();
  4227. for i = 1, 16 do
  4228. tinsert(self.sparkles, _G[name .. i]);
  4229. end
  4230. end
  4231. function AutoCastShine_AutoCastStart(button, r, g, b)
  4232. if ( AUTOCAST_SHINES[button] ) then
  4233. return;
  4234. end
  4235. AUTOCAST_SHINES[button] = true;
  4236. if ( not r ) then
  4237. r, g, b = AUTOCAST_SHINE_R, AUTOCAST_SHINE_G, AUTOCAST_SHINE_B;
  4238. end
  4239. for _, sparkle in next, button.sparkles do
  4240. sparkle:Show();
  4241. sparkle:SetVertexColor(r, g, b);
  4242. end
  4243. end
  4244. function AutoCastShine_AutoCastStop(button)
  4245. AUTOCAST_SHINES[button] = nil;
  4246. for _, sparkle in next, button.sparkles do
  4247. sparkle:Hide();
  4248. end
  4249. end
  4250. function AutoCastShine_OnUpdate(self, elapsed)
  4251. for i in next, AUTOCAST_SHINE_TIMERS do
  4252. AUTOCAST_SHINE_TIMERS[i] = AUTOCAST_SHINE_TIMERS[i] + elapsed;
  4253. if ( AUTOCAST_SHINE_TIMERS[i] > AUTOCAST_SHINE_SPEEDS[i]*4 ) then
  4254. AUTOCAST_SHINE_TIMERS[i] = 0;
  4255. end
  4256. end
  4257. for button in next, AUTOCAST_SHINES do
  4258. self = button;
  4259. local parent, distance = self, self:GetWidth();
  4260. -- 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.
  4261. local AUTOCAST_SHINE_SPACING = 6;
  4262. for i = 1, 4 do
  4263. local timer = AUTOCAST_SHINE_TIMERS[i];
  4264. local speed = AUTOCAST_SHINE_SPEEDS[i];
  4265. if ( timer <= speed ) then
  4266. local basePosition = timer/speed*distance;
  4267. self.sparkles[0+i]:SetPoint("CENTER", parent, "TOPLEFT", basePosition, 0);
  4268. self.sparkles[4+i]:SetPoint("CENTER", parent, "BOTTOMRIGHT", -basePosition, 0);
  4269. self.sparkles[8+i]:SetPoint("CENTER", parent, "TOPRIGHT", 0, -basePosition);
  4270. self.sparkles[12+i]:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, basePosition);
  4271. elseif ( timer <= speed*2 ) then
  4272. local basePosition = (timer-speed)/speed*distance;
  4273. self.sparkles[0+i]:SetPoint("CENTER", parent, "TOPRIGHT", 0, -basePosition);
  4274. self.sparkles[4+i]:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, basePosition);
  4275. self.sparkles[8+i]:SetPoint("CENTER", parent, "BOTTOMRIGHT", -basePosition, 0);
  4276. self.sparkles[12+i]:SetPoint("CENTER", parent, "TOPLEFT", basePosition, 0);
  4277. elseif ( timer <= speed*3 ) then
  4278. local basePosition = (timer-speed*2)/speed*distance;
  4279. self.sparkles[0+i]:SetPoint("CENTER", parent, "BOTTOMRIGHT", -basePosition, 0);
  4280. self.sparkles[4+i]:SetPoint("CENTER", parent, "TOPLEFT", basePosition, 0);
  4281. self.sparkles[8+i]:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, basePosition);
  4282. self.sparkles[12+i]:SetPoint("CENTER", parent, "TOPRIGHT", 0, -basePosition);
  4283. else
  4284. local basePosition = (timer-speed*3)/speed*distance;
  4285. self.sparkles[0+i]:SetPoint("CENTER", parent, "BOTTOMLEFT", 0, basePosition);
  4286. self.sparkles[4+i]:SetPoint("CENTER", parent, "TOPRIGHT", 0, -basePosition);
  4287. self.sparkles[8+i]:SetPoint("CENTER", parent, "TOPLEFT", basePosition, 0);
  4288. self.sparkles[12+i]:SetPoint("CENTER", parent, "BOTTOMRIGHT", -basePosition, 0);
  4289. end
  4290. end
  4291. end
  4292. end
  4293. function ConsolePrint(...)
  4294. ConsoleAddMessage(strjoin(" ", tostringall(...)));
  4295. end
  4296. function LFD_IsEmpowered()
  4297. --Solo players are always empowered.
  4298. if ( not IsInGroup() ) then
  4299. return true;
  4300. end
  4301. --The leader may always queue/dequeue
  4302. if ( UnitIsGroupLeader("player") ) then
  4303. return true;
  4304. end
  4305. --In DF groups, anyone may queue/dequeue. In RF groups, the leader or assistants may queue/dequeue.
  4306. if ( HasLFGRestrictions() and (not IsInRaid() or UnitIsGroupAssistant("player")) ) then
  4307. return true;
  4308. end
  4309. return false;
  4310. end
  4311. function RaidBrowser_IsEmpowered()
  4312. return (not IsInGroup()) or UnitIsGroupLeader("player");
  4313. end
  4314. function GetLFGMode(category, lfgID)
  4315. if ( category ~= LE_LFG_CATEGORY_RF ) then
  4316. lfgID = nil; --HACK - RF works differently from everything else. You can queue for multiple RF slots with different ride tickets.
  4317. end
  4318. local proposalExists, id, typeID, subtypeID, name, texture, role, hasResponded, totalEncounters, completedEncounters, numMembers, isLeader, isHoliday, proposalCategory = GetLFGProposal();
  4319. local inParty, joined, queued, noPartialClear, achievements, lfgComment, slotCount = GetLFGInfoServer(category, lfgID);
  4320. local roleCheckInProgress, slots, members, roleUpdateCategory, roleUpdateID = GetLFGRoleUpdate();
  4321. local partyCategory = nil;
  4322. local partySlot = GetPartyLFGID();
  4323. if ( partySlot ) then
  4324. partyCategory = GetLFGCategoryForID(partySlot);
  4325. end
  4326. local empoweredFunc = LFD_IsEmpowered;
  4327. if ( category == LE_LFG_CATEGORY_LFR ) then
  4328. empoweredFunc = RaidBrowser_IsEmpowered;
  4329. end
  4330. if ( proposalExists and not hasResponded and proposalCategory == category and (not lfgID or lfgID == id) ) then
  4331. return "proposal", "unaccepted";
  4332. elseif ( proposalExists and proposalCategory == category and (not lfgID or lfgID == id) ) then
  4333. return "proposal", "accepted";
  4334. elseif ( queued ) then
  4335. return "queued", (empoweredFunc() and "empowered" or "unempowered");
  4336. elseif ( roleCheckInProgress and roleUpdateCategory == category and (not lfgID or lfgID == roleUpdateID) ) then
  4337. return "rolecheck";
  4338. elseif ( category == LE_LFG_CATEGORY_LFR and joined ) then
  4339. return "listed", (empoweredFunc() and "empowered" or "unempowered");
  4340. elseif ( joined ) then
  4341. return "suspended", (empoweredFunc() and "empowered" or "unempowered"); --We are "joined" to LFG, but not actually queued right now.
  4342. elseif ( IsInGroup() and IsPartyLFG() and partyCategory == category and (not lfgID or lfgID == partySlot) ) then
  4343. if IsAllowedToUserTeleport() then
  4344. return "lfgparty", "teleport";
  4345. end
  4346. if IsLFGComplete() then
  4347. return "lfgparty", "complete";
  4348. end
  4349. return "lfgparty", "noteleport";
  4350. elseif ( IsPartyLFG() and IsInLFGDungeon() and partyCategory == category and (not lfgID or lfgID == partySlot) ) then
  4351. return "abandonedInDungeon";
  4352. end
  4353. end
  4354. function IsLFGModeActive(category)
  4355. local partySlot = GetPartyLFGID();
  4356. local partyCategory = nil;
  4357. if ( partySlot ) then
  4358. partyCategory = GetLFGCategoryForID(partySlot);
  4359. end
  4360. if ( partyCategory == category ) then
  4361. return true;
  4362. end
  4363. return false;
  4364. end
  4365. --Like date(), but localizes AM/PM. In the future, could also localize other stuff.
  4366. function BetterDate(formatString, timeVal)
  4367. local dateTable = date("*t", timeVal);
  4368. local amString = (dateTable.hour >= 12) and TIMEMANAGER_PM or TIMEMANAGER_AM;
  4369. --First, we'll replace %p with the appropriate AM or PM.
  4370. formatString = gsub(formatString, "^%%p", amString) --Replaces %p at the beginning of the string with the am/pm token
  4371. formatString = gsub(formatString, "([^%%])%%p", "%1"..amString); -- Replaces %p anywhere else in the string, but doesn't replace %%p (since the first % escapes the second)
  4372. return date(formatString, timeVal);
  4373. end
  4374. function GMError(...)
  4375. if ( IsGMClient() ) then
  4376. error(...);
  4377. end
  4378. end
  4379. function OnExcessiveErrors()
  4380. StaticPopup_Show("TOO_MANY_LUA_ERRORS");
  4381. end
  4382. function SetLargeGuildTabardTextures(unit, emblemTexture, backgroundTexture, borderTexture, tabardData)
  4383. -- texure dimensions are 1024x1024, icon dimensions are 64x64
  4384. local emblemSize, columns, offset;
  4385. if ( emblemTexture ) then
  4386. emblemSize = 64 / 1024;
  4387. columns = 16
  4388. offset = 0;
  4389. emblemTexture:SetTexture("Interface\\GuildFrame\\GuildEmblemsLG_01");
  4390. end
  4391. local hasEmblem = SetGuildTabardTextures(emblemSize, columns, offset, unit, emblemTexture, backgroundTexture, borderTexture, tabardData);
  4392. emblemTexture:SetWidth(hasEmblem and (emblemTexture:GetHeight() * (7 / 8)) or emblemTexture:GetHeight());
  4393. end
  4394. function SetSmallGuildTabardTextures(unit, emblemTexture, backgroundTexture, borderTexture, tabardData)
  4395. -- texure dimensions are 256x256, icon dimensions are 16x16, centered in 18x18 cells
  4396. local emblemSize, columns, offset;
  4397. if ( emblemTexture ) then
  4398. emblemSize = 18 / 256;
  4399. columns = 14;
  4400. offset = 1 / 256;
  4401. emblemTexture:SetTexture("Interface\\GuildFrame\\GuildEmblems_01");
  4402. end
  4403. SetGuildTabardTextures(emblemSize, columns, offset, unit, emblemTexture, backgroundTexture, borderTexture, tabardData);
  4404. end
  4405. function SetDoubleGuildTabardTextures(unit, leftEmblemTexture, rightEmblemTexture, backgroundTexture, borderTexture, tabardData)
  4406. if ( leftEmblemTexture and rightEmblemTexture ) then
  4407. SetGuildTabardTextures(nil, nil, nil, unit, leftEmblemTexture, backgroundTexture, borderTexture, tabardData);
  4408. rightEmblemTexture:SetTexture(leftEmblemTexture:GetTexture());
  4409. rightEmblemTexture:SetVertexColor(leftEmblemTexture:GetVertexColor());
  4410. end
  4411. end
  4412. function SetGuildTabardTextures(emblemSize, columns, offset, unit, emblemTexture, backgroundTexture, borderTexture, tabardData)
  4413. local backgroundColor, borderColor, emblemColor, emblemFileID, emblemIndex;
  4414. tabardData = tabardData or C_GuildInfo.GetGuildTabardInfo(unit);
  4415. if(tabardData) then
  4416. backgroundColor = tabardData.backgroundColor;
  4417. borderColor = tabardData.borderColor;
  4418. emblemColor = tabardData.emblemColor;
  4419. emblemFileID = tabardData.emblemFileID;
  4420. emblemIndex = tabardData.emblemStyle;
  4421. end
  4422. if (emblemFileID) then
  4423. if (backgroundTexture) then
  4424. backgroundTexture:SetVertexColor(backgroundColor:GetRGB());
  4425. end
  4426. if (borderTexture) then
  4427. borderTexture:SetVertexColor(borderColor:GetRGB());
  4428. end
  4429. if (emblemSize) then
  4430. if (emblemIndex) then
  4431. local xCoord = mod(emblemIndex, columns) * emblemSize;
  4432. local yCoord = floor(emblemIndex / columns) * emblemSize;
  4433. emblemTexture:SetTexCoord(xCoord + offset, xCoord + emblemSize - offset, yCoord + offset, yCoord + emblemSize - offset);
  4434. end
  4435. emblemTexture:SetVertexColor(emblemColor:GetRGB());
  4436. elseif (emblemTexture) then
  4437. emblemTexture:SetTexture(emblemFileID);
  4438. emblemTexture:SetVertexColor(emblemColor:GetRGB());
  4439. end
  4440. return true;
  4441. else
  4442. -- tabard lacks design
  4443. if (backgroundTexture) then
  4444. backgroundTexture:SetVertexColor(0.2245, 0.2088, 0.1794);
  4445. end
  4446. if (borderTexture) then
  4447. borderTexture:SetVertexColor(0.2, 0.2, 0.2);
  4448. end
  4449. if (emblemTexture) then
  4450. if (emblemSize) then
  4451. if (emblemSize == 18 / 256) then
  4452. emblemTexture:SetTexture("Interface\\GuildFrame\\GuildLogo-NoLogoSm");
  4453. else
  4454. emblemTexture:SetTexture("Interface\\GuildFrame\\GuildLogo-NoLogo");
  4455. end
  4456. emblemTexture:SetTexCoord(0, 1, 0, 1);
  4457. emblemTexture:SetVertexColor(1, 1, 1, 1);
  4458. else
  4459. emblemTexture:SetTexture("");
  4460. end
  4461. end
  4462. return false;
  4463. end
  4464. end
  4465. function GetDisplayedAllyFrames()
  4466. local useCompact = GetCVarBool("useCompactPartyFrames")
  4467. if ( IsActiveBattlefieldArena() and not useCompact and not C_PvP.IsInBrawl() ) then
  4468. return "party";
  4469. elseif ( IsInGroup() and (IsInRaid() or useCompact) ) then
  4470. return "raid";
  4471. elseif ( IsInGroup() ) then
  4472. return "party";
  4473. else
  4474. return nil;
  4475. end
  4476. end
  4477. local displayedCapMessage = false;
  4478. function TrialAccountCapReached_Inform(capType)
  4479. if ( displayedCapMessage or not GameLimitedMode_IsActive() ) then
  4480. return;
  4481. end
  4482. local info = ChatTypeInfo.SYSTEM;
  4483. if ( capType == "level" ) then
  4484. DEFAULT_CHAT_FRAME:AddMessage(CAPPED_LEVEL_TRIAL, info.r, info.g, info.b);
  4485. elseif ( capType == "money" ) then
  4486. DEFAULT_CHAT_FRAME:AddMessage(CAPPED_MONEY_TRIAL, info.r, info.g, info.b);
  4487. end
  4488. displayedCapMessage = true;
  4489. end
  4490. function AbbreviateLargeNumbers(value)
  4491. local strLen = strlen(value);
  4492. local retString = value;
  4493. if ( strLen > 8 ) then
  4494. retString = string.sub(value, 1, -7)..SECOND_NUMBER_CAP;
  4495. elseif ( strLen > 5 ) then
  4496. retString = string.sub(value, 1, -4)..FIRST_NUMBER_CAP;
  4497. elseif (strLen > 3 ) then
  4498. retString = BreakUpLargeNumbers(value);
  4499. end
  4500. return retString;
  4501. end
  4502. NUMBER_ABBREVIATION_DATA = {
  4503. -- Order these from largest to smallest
  4504. -- (significandDivisor and fractionDivisor should multiply to be equal to breakpoint)
  4505. { breakpoint = 10000000000000, abbreviation = FOURTH_NUMBER_CAP_NO_SPACE, significandDivisor = 1000000000000, fractionDivisor = 1 },
  4506. { breakpoint = 1000000000000, abbreviation = FOURTH_NUMBER_CAP_NO_SPACE, significandDivisor = 100000000000, fractionDivisor = 10 },
  4507. { breakpoint = 10000000000, abbreviation = THIRD_NUMBER_CAP_NO_SPACE, significandDivisor = 1000000000, fractionDivisor = 1 },
  4508. { breakpoint = 1000000000, abbreviation = THIRD_NUMBER_CAP_NO_SPACE, significandDivisor = 100000000, fractionDivisor = 10 },
  4509. { breakpoint = 10000000, abbreviation = SECOND_NUMBER_CAP_NO_SPACE, significandDivisor = 1000000, fractionDivisor = 1 },
  4510. { breakpoint = 1000000, abbreviation = SECOND_NUMBER_CAP_NO_SPACE, significandDivisor = 100000, fractionDivisor = 10 },
  4511. { breakpoint = 10000, abbreviation = FIRST_NUMBER_CAP_NO_SPACE, significandDivisor = 1000, fractionDivisor = 1 },
  4512. { breakpoint = 1000, abbreviation = FIRST_NUMBER_CAP_NO_SPACE, significandDivisor = 100, fractionDivisor = 10 },
  4513. }
  4514. function AbbreviateNumbers(value)
  4515. for i, data in ipairs(NUMBER_ABBREVIATION_DATA) do
  4516. if value >= data.breakpoint then
  4517. local finalValue = math.floor(value / data.significandDivisor) / data.fractionDivisor;
  4518. return finalValue .. data.abbreviation;
  4519. end
  4520. end
  4521. return tostring(value);
  4522. end
  4523. function IsInLFDBattlefield()
  4524. return IsLFGModeActive(LE_LFG_CATEGORY_BATTLEFIELD);
  4525. end
  4526. function LeaveInstanceParty()
  4527. if ( IsInLFDBattlefield() ) then
  4528. local currentMapID, _, lfgID = select(8, GetInstanceInfo());
  4529. local _, typeID, subtypeID, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, lfgMapID = GetLFGDungeonInfo(lfgID);
  4530. if currentMapID == lfgMapID and subtypeID == LE_LFG_CATEGORY_BATTLEFIELD then
  4531. LFGTeleport(true);
  4532. return;
  4533. end
  4534. end
  4535. C_PartyInfo.LeaveParty(LE_PARTY_CATEGORY_INSTANCE);
  4536. end
  4537. function ConfirmOrLeaveLFGParty()
  4538. if ( not IsInGroup(LE_PARTY_CATEGORY_INSTANCE) ) then
  4539. return;
  4540. end
  4541. if ( IsPartyLFG() and not IsLFGComplete() ) then
  4542. local partyLFGSlot = GetPartyLFGID();
  4543. local partyLFGCategory = nil;
  4544. if ( partyLFGSlot ) then
  4545. partyLFGCategory = GetLFGCategoryForID(partyLFGSlot);
  4546. end
  4547. StaticPopup_Show("CONFIRM_LEAVE_INSTANCE_PARTY", partyLFGCategory == LE_LFG_CATEGORY_WORLDPVP and CONFIRM_LEAVE_BATTLEFIELD or CONFIRM_LEAVE_INSTANCE_PARTY);
  4548. else
  4549. LeaveInstanceParty();
  4550. end
  4551. end
  4552. function ConfirmOrLeaveBattlefield()
  4553. if ( GetBattlefieldWinner() ) then
  4554. LeaveBattlefield();
  4555. else
  4556. StaticPopup_Show("CONFIRM_LEAVE_BATTLEFIELD");
  4557. end
  4558. end
  4559. function ConfirmSurrenderArena()
  4560. StaticPopup_Show("CONFIRM_SURRENDER_ARENA");
  4561. end
  4562. function GetCurrentScenarioType()
  4563. local scenarioType = select(10, C_Scenario.GetInfo());
  4564. return scenarioType;
  4565. end
  4566. function IsBoostTutorialScenario()
  4567. return GetCurrentScenarioType() == LE_SCENARIO_TYPE_BOOST_TUTORIAL;
  4568. end
  4569. function PrintLootSpecialization()
  4570. local specID = GetLootSpecialization();
  4571. local sex = UnitSex("player");
  4572. local lootSpecChoice;
  4573. if ( specID and specID > 0 ) then
  4574. local id, name = GetSpecializationInfoByID(specID, sex);
  4575. lootSpecChoice = format(ERR_LOOT_SPEC_CHANGED_S, name);
  4576. --[[ else
  4577. local specIndex = GetSpecialization();
  4578. if ( specIndex) then
  4579. local specID, specName = GetSpecializationInfo(specIndex, nil, nil, nil, sex);
  4580. if ( specName ) then
  4581. lootSpecChoice = format(ERR_LOOT_SPEC_CHANGED_S, format(LOOT_SPECIALIZATION_DEFAULT, specName));
  4582. end
  4583. end]]
  4584. end
  4585. if ( lootSpecChoice ) then
  4586. local info = ChatTypeInfo["SYSTEM"];
  4587. DEFAULT_CHAT_FRAME:AddMessage(lootSpecChoice, info.r, info.g, info.b, info.id);
  4588. end
  4589. end
  4590. function BuildIconArray(parent, baseName, template, rowSize, numRows, onButtonCreated)
  4591. local previousButton = CreateFrame("CheckButton", baseName.."1", parent, template);
  4592. local cornerButton = previousButton;
  4593. previousButton:SetID(1);
  4594. previousButton:SetPoint("TOPLEFT", 26, -85);
  4595. if ( onButtonCreated ) then
  4596. onButtonCreated(parent, previousButton);
  4597. end
  4598. local numIcons = rowSize * numRows;
  4599. for i = 2, numIcons do
  4600. local newButton = CreateFrame("CheckButton", baseName..i, parent, template);
  4601. newButton:SetID(i);
  4602. if ( i % rowSize == 1 ) then
  4603. newButton:SetPoint("TOPLEFT", cornerButton, "BOTTOMLEFT", 0, -8);
  4604. cornerButton = newButton;
  4605. else
  4606. newButton:SetPoint("LEFT", previousButton, "RIGHT", 10, 0);
  4607. end
  4608. previousButton = newButton;
  4609. newButton:Hide();
  4610. if ( onButtonCreated ) then
  4611. onButtonCreated(parent, newButton);
  4612. end
  4613. end
  4614. end
  4615. function GetSmoothProgressChange(value, displayedValue, range, elapsed, minPerSecond, maxPerSecond)
  4616. maxPerSecond = maxPerSecond or 0.7;
  4617. minPerSecond = minPerSecond or 0.3;
  4618. minPerSecond = max(minPerSecond, 1/range); --Make sure we're moving at least 1 unit/second (will only matter if our maximum power is 3 or less);
  4619. local diff = displayedValue - value;
  4620. local diffRatio = diff / range;
  4621. local change = range * ((minPerSecond/abs(diffRatio) + maxPerSecond - minPerSecond) * diffRatio) * elapsed;
  4622. if ( abs(change) > abs(diff) or abs(diffRatio) < 0.01 ) then
  4623. return value;
  4624. else
  4625. return displayedValue - change;
  4626. end
  4627. end
  4628. function InGlue()
  4629. return false;
  4630. end
  4631. function RGBToColorCode(r, g, b)
  4632. return format("|cff%02x%02x%02x", r*255, g*255, b*255);
  4633. end
  4634. function RGBTableToColorCode(rgbTable)
  4635. return RGBToColorCode(rgbTable.r, rgbTable.g, rgbTable.b);
  4636. end
  4637. function WillAcceptInviteRemoveQueues()
  4638. --Dungeon/Raid Finder
  4639. for i=1, NUM_LE_LFG_CATEGORYS do
  4640. local mode = GetLFGMode(i);
  4641. if ( mode and mode ~= "lfgparty" ) then
  4642. return true;
  4643. end
  4644. end
  4645. --Don't need to look at LFGList listings because we can't accept invites while in one
  4646. --LFGList applications
  4647. local apps = C_LFGList.GetApplications();
  4648. for i=1, #apps do
  4649. local _, appStatus = C_LFGList.GetApplicationInfo(apps[i]);
  4650. if ( appStatus == "applied" or appStatus == "invited" ) then
  4651. return true;
  4652. end
  4653. end
  4654. --PvP
  4655. for i=1, GetMaxBattlefieldID() do
  4656. local status, mapName, teamSize, registeredMatch, suspend = GetBattlefieldStatus(i);
  4657. if ( status == "queued" or status == "confirmed" ) then
  4658. return true;
  4659. end
  4660. end
  4661. return false;
  4662. end
  4663. --Only really works on friends and guild-mates
  4664. function GetDisplayedInviteType(guid)
  4665. if ( IsInGroup() ) then
  4666. if ( UnitIsGroupLeader("player") or UnitIsGroupAssistant("player") ) then
  4667. return "INVITE";
  4668. else
  4669. return "SUGGEST_INVITE";
  4670. end
  4671. else
  4672. if ( not guid ) then
  4673. return "INVITE";
  4674. end
  4675. local party, isSoloQueueParty = C_SocialQueue.GetGroupForPlayer(guid);
  4676. if ( party and not isSoloQueueParty ) then --In a real party, not a secret hidden party for solo queuing
  4677. return "REQUEST_INVITE";
  4678. elseif ( WillAcceptInviteRemoveQueues() ) then
  4679. return "INVITE";
  4680. elseif ( party ) then --They are queued solo for something
  4681. return "REQUEST_INVITE";
  4682. else
  4683. return "INVITE";
  4684. end
  4685. end
  4686. end
  4687. function nop()
  4688. end
  4689. function ShakeFrameRandom(frame, magnitude, duration, frequency)
  4690. if frequency <= 0 then
  4691. return;
  4692. end
  4693. local shake = {};
  4694. for i = 1, math.ceil(duration / frequency) do
  4695. local xVariation, yVariation = RandomFloatInRange(-magnitude, magnitude), RandomFloatInRange(-magnitude, magnitude);
  4696. shake[i] = { x = xVariation, y = yVariation };
  4697. end
  4698. ShakeFrame(frame, shake, duration, frequency);
  4699. end
  4700. function ShakeFrame(frame, shake, maximumDuration, frequency)
  4701. if ( frame.shakeTicker and not frame.shakeTicker:IsCancelled() ) then
  4702. return;
  4703. end
  4704. local point, relativeFrame, relativePoint, x, y = frame:GetPoint();
  4705. local shakeIndex = 1;
  4706. local endTime = GetTime() + maximumDuration;
  4707. frame.shakeTicker = C_Timer.NewTicker(frequency, function()
  4708. local xVariation, yVariation = shake[shakeIndex].x, shake[shakeIndex].y;
  4709. frame:SetPoint(point, relativeFrame, relativePoint, x + xVariation, y + yVariation);
  4710. shakeIndex = shakeIndex + 1;
  4711. if shakeIndex > #shake or GetTime() >= endTime then
  4712. frame:SetPoint(point, relativeFrame, relativePoint, x, y);
  4713. frame.shakeTicker:Cancel();
  4714. end
  4715. end);
  4716. end
  4717. -- Currency Overflow --
  4718. function WillCurrencyRewardOverflow(currencyID, rewardQuantity)
  4719. local name, quantity, icon, earnedThisWeek, weeklyMax, maxQuantity, discovered, rarity = GetCurrencyInfo(currencyID);
  4720. return maxQuantity > 0 and rewardQuantity + quantity > maxQuantity;
  4721. end
  4722. function GetColorForCurrencyReward(currencyID, rewardQuantity, defaultColor)
  4723. if WillCurrencyRewardOverflow(currencyID, rewardQuantity) then
  4724. return RED_FONT_COLOR;
  4725. elseif defaultColor then
  4726. return defaultColor;
  4727. else
  4728. return HIGHLIGHT_FONT_COLOR;
  4729. end
  4730. end
  4731. function GetSortedSelfResurrectOptions()
  4732. local options = C_DeathInfo.GetSelfResurrectOptions();
  4733. if ( not options ) then
  4734. return nil;
  4735. end
  4736. table.sort(options, function(a, b)
  4737. if ( a.canUse ~= b.canUse ) then
  4738. return a.canUse;
  4739. end
  4740. if ( a.isLimited ~= b.isLimited ) then
  4741. return not a.isLimited;
  4742. end
  4743. -- lowest priority is first
  4744. return a.priority < b.priority end
  4745. );
  4746. return options;
  4747. end
  4748. function OpenAchievementFrameToAchievement(achievementID)
  4749. if ( not AchievementFrame ) then
  4750. AchievementFrame_LoadUI();
  4751. end
  4752. if ( not AchievementFrame:IsShown() ) then
  4753. AchievementFrame_ToggleAchievementFrame();
  4754. end
  4755. AchievementFrame_SelectAchievement(achievementID);
  4756. end
  4757. function ChatClassColorOverrideShown()
  4758. local value = GetCVar("chatClassColorOverride");
  4759. if value == "0" then
  4760. return true;
  4761. elseif value == "1" then
  4762. return false;
  4763. else
  4764. return nil;
  4765. end
  4766. end
  4767. -- takes into account the current expansion
  4768. -- NOTE: it's not safe to cache this value as it could change in the middle of the session
  4769. function GetEffectivePlayerMaxLevel()
  4770. return MAX_PLAYER_LEVEL_TABLE[GetExpansionLevel()];
  4771. end
  4772. function IsLevelAtEffectiveMaxLevel(level)
  4773. return level >= GetEffectivePlayerMaxLevel();
  4774. end
  4775. function IsPlayerAtEffectiveMaxLevel()
  4776. return IsLevelAtEffectiveMaxLevel(UnitLevel("player"));
  4777. end
  4778. function DisplayInterfaceActionBlockedMessage()
  4779. if ( not INTERFACE_ACTION_BLOCKED_SHOWN ) then
  4780. local info = ChatTypeInfo["SYSTEM"];
  4781. DEFAULT_CHAT_FRAME:AddMessage(INTERFACE_ACTION_BLOCKED, info.r, info.g, info.b, info.id);
  4782. INTERFACE_ACTION_BLOCKED_SHOWN = true;
  4783. end
  4784. end