UIParent.lua

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