Advertisement
Guest User

Untitled

a guest
Nov 28th, 2014
455
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 328.26 KB | None | 0 0
  1. -- Lua APIs
  2. local tinsert, tconcat, tremove, wipe = table.insert, table.concat, table.remove, wipe
  3. local fmt, tostring, string_char = string.format, tostring, string.char
  4. local select, pairs, next, type, unpack = select, pairs, next, type, unpack
  5. local loadstring, assert, error = loadstring, assert, error
  6. local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
  7. local bit_band, bit_lshift, bit_rshift = bit.band, bit.lshift, bit.rshift
  8. local coroutine = coroutine
  9.  
  10. local LDB = LibStub:GetLibrary("LibDataBroker-1.1");
  11. local AceGUI = LibStub("AceGUI-3.0");
  12. local AceConfig = LibStub("AceConfig-3.0");
  13. local AceConfigRegistry = LibStub("AceConfigRegistry-3.0");
  14. local AceConfigDialog = LibStub("AceConfigDialog-3.0");
  15.  
  16. local WeakAuras = WeakAuras
  17. local L = WeakAuras.L;
  18.  
  19. local ADDON_NAME = "WeakAurasOptions";
  20.  
  21. local GetSpellInfo = GetSpellInfo;
  22. local GetItemInfo = GetItemInfo;
  23.  
  24. local font_close,yellow_font,red_font = FONT_COLOR_CODE_CLOSE,YELLOW_FONT_COLOR_CODE,RED_FONT_COLOR_CODE
  25. local ValidateNumeric = function(info,val)
  26. if not tonumber(val) then
  27. return print(fmt("|cff9900FF"..ADDON_NAME..font_close..":"..yellow_font.." %s"..red_font.." is not a number!",tostring(val)))
  28. end
  29. return true
  30. end
  31.  
  32. -- Handle coroutines
  33. local dynFrame = {};
  34. do
  35. -- Internal data
  36. dynFrame.frame = CreateFrame("frame");
  37. dynFrame.update = {};
  38. dynFrame.size = 0;
  39.  
  40. -- Add an action to be resumed via OnUpdate
  41. function dynFrame.AddAction(self, name, func)
  42. if not name then
  43. name = fmt("NIL", dynFrame.size+1);
  44. end
  45.  
  46. if not dynFrame.update[name] then
  47. dynFrame.update[name] = func;
  48. dynFrame.size = dynFrame.size + 1
  49.  
  50. dynFrame.frame:Show();
  51. end
  52. end
  53.  
  54. -- Remove an action from OnUpdate
  55. function dynFrame.RemoveAction(self, name)
  56. if dynFrame.update[name] then
  57. dynFrame.update[name] = nil;
  58. dynFrame.size = dynFrame.size - 1
  59.  
  60. if dynFrame.size == 0 then
  61. dynFrame.frame:Hide();
  62. end
  63. end
  64. end
  65.  
  66. -- Setup frame
  67. dynFrame.frame:Hide();
  68. dynFrame.frame:SetScript("OnUpdate", function(self, elapsed)
  69. -- Start timing
  70. local start = debugprofilestop();
  71. local hasData = true;
  72.  
  73. -- Resume as often as possible (Limit to 16ms per frame -> 60 FPS)
  74. while (debugprofilestop() - start < 16 and hasData) do
  75. -- Stop loop without data
  76. hasData = false;
  77.  
  78. -- Resume all coroutines
  79. for name, func in pairs(dynFrame.update) do
  80. -- Loop has data
  81. hasData = true;
  82.  
  83. -- Resume or remove
  84. if coroutine.status(func) ~= "dead" then
  85. local err,ret1,ret2 = assert(coroutine.resume(func))
  86. if err then
  87. WeakAuras.debug(debugstack(func))
  88. end
  89. else
  90. dynFrame:RemoveAction(name);
  91. end
  92. end
  93. end
  94. end);
  95. end
  96. WeakAuras.transmitCache = {};
  97.  
  98. local iconCache = {};
  99. local idCache = {};
  100. local talentCache = {};
  101.  
  102. local regionOptions = WeakAuras.regionOptions;
  103. local displayButtons = {};
  104. WeakAuras.displayButtons = displayButtons;
  105. local optionReloads = {};
  106. local optionTriggerChoices = {};
  107. WeakAuras.thumbnails = {};
  108. local thumbnails = WeakAuras.thumbnails;
  109. local displayOptions = {};
  110. WeakAuras.displayOptions = displayOptions;
  111. local loaded = WeakAuras.loaded;
  112.  
  113. local tempGroup = {
  114. id = {"tempGroup"},
  115. regionType = "group",
  116. controlledChildren = {},
  117. load = {},
  118. trigger = {},
  119. anchorPoint = "CENTER",
  120. xOffset = 0,
  121. yOffset = 0
  122. };
  123. function WeakAuras.MultipleDisplayTooltipDesc()
  124. local desc = {{L["Multiple Displays"], L["Temporary Group"]}};
  125. for index, id in pairs(tempGroup.controlledChildren) do
  126. desc[index + 1] = {" ", id};
  127. end
  128. desc[2][1] = L["Children:"]
  129. tinsert(desc, " ");
  130. tinsert(desc, {" ", "|cFF00FFFF"..L["Right-click for more options"]});
  131. return desc;
  132. end
  133. function WeakAuras.MultipleDisplayTooltipMenu()
  134. local menu = {
  135. {
  136. text = L["Add to new Group"],
  137. notCheckable = 1,
  138. func = function()
  139. local new_id = tempGroup.controlledChildren[1].." Group";
  140. local num = 2;
  141. while(WeakAuras.GetData(new_id)) do
  142. new_id = "New "..num;
  143. num = num + 1;
  144. end
  145.  
  146. local data = {
  147. id = new_id,
  148. regionType = "group",
  149. trigger = {},
  150. load = {}
  151. };
  152. WeakAuras.Add(data);
  153. WeakAuras.NewDisplayButton(data);
  154.  
  155. for index, childId in pairs(tempGroup.controlledChildren) do
  156. local childData = WeakAuras.GetData(childId);
  157. tinsert(data.controlledChildren, childId);
  158. childData.parent = data.id;
  159. WeakAuras.Add(data);
  160. WeakAuras.Add(childData);
  161. end
  162.  
  163. for index, id in pairs(data.controlledChildren) do
  164. local childButton = WeakAuras.GetDisplayButton(id);
  165. childButton:SetGroup(data.id, data.regionType == "dynamicgroup");
  166. childButton:SetGroupOrder(index, #data.controlledChildren);
  167. end
  168.  
  169. local button = WeakAuras.GetDisplayButton(data.id);
  170. button.callbacks.UpdateExpandButton();
  171. WeakAuras.UpdateDisplayButton(data);
  172. WeakAuras.ReloadGroupRegionOptions(data);
  173. WeakAuras.SortDisplayButtons();
  174. button:Expand();
  175. end
  176. },
  177. {
  178. text = L["Add to new Dynamic Group"],
  179. notCheckable = 1,
  180. func = function()
  181. local new_id = tempGroup.controlledChildren[1].." Group";
  182. local num = 2;
  183. while(WeakAuras.GetData(new_id)) do
  184. new_id = "New "..num;
  185. num = num + 1;
  186. end
  187.  
  188. local data = {
  189. id = new_id,
  190. regionType = "dynamicgroup",
  191. trigger = {},
  192. load = {}
  193. };
  194. WeakAuras.Add(data);
  195. WeakAuras.NewDisplayButton(data);
  196.  
  197. for index, childId in pairs(tempGroup.controlledChildren) do
  198. local childData = WeakAuras.GetData(childId);
  199. tinsert(data.controlledChildren, childId);
  200. childData.parent = data.id;
  201. WeakAuras.Add(data);
  202. WeakAuras.Add(childData);
  203. end
  204.  
  205. for index, id in pairs(data.controlledChildren) do
  206. local childButton = WeakAuras.GetDisplayButton(id);
  207. childButton:SetGroup(data.id, data.regionType == "dynamicgroup");
  208. childButton:SetGroupOrder(index, #data.controlledChildren);
  209. end
  210.  
  211. local button = WeakAuras.GetDisplayButton(data.id);
  212. button.callbacks.UpdateExpandButton();
  213. WeakAuras.UpdateDisplayButton(data);
  214. WeakAuras.ReloadGroupRegionOptions(data);
  215. WeakAuras.SortDisplayButtons();
  216. button:Expand();
  217. end
  218. },
  219. {
  220. text = " ",
  221. notCheckable = 1,
  222. notClickable = 1
  223. },
  224. {
  225. text = L["Delete all"],
  226. notCheckable = 1,
  227. func = function()
  228. for index, id in pairs(tempGroup.controlledChildren) do
  229. local toDelete = {};
  230. local parents = {};
  231. for index, id in pairs(tempGroup.controlledChildren) do
  232. local childData = WeakAuras.GetData(id);
  233. toDelete[index] = childData;
  234. if(childData.parent) then
  235. parents[childData.parent] = true;
  236. end
  237. end
  238. for index, childData in pairs(toDelete) do
  239. WeakAuras.DeleteOption(childData);
  240. end
  241. for id, _ in pairs(parents) do
  242. local parentData = WeakAuras.GetData(id);
  243. local parentButton = WeakAuras.GetDisplayButton(id);
  244. WeakAuras.UpdateGroupOrders(parentData);
  245. if(#parentData.controlledChildren == 0) then
  246. parentButton:DisableExpand();
  247. else
  248. parentButton:EnableExpand();
  249. end
  250. parentButton:SetNormalTooltip();
  251. end
  252. end
  253. WeakAuras.SortDisplayButtons();
  254. end
  255. },
  256. {
  257. text = " ",
  258. notClickable = 1,
  259. notCheckable = 1,
  260. },
  261. {
  262. text = L["Close"],
  263. notCheckable = 1,
  264. func = function() WeakAuras_DropDownMenu:Hide() end
  265. }
  266. };
  267. local anyGrouped = false;
  268. for index, id in pairs(tempGroup.controlledChildren) do
  269. local childData = WeakAuras.GetData(id);
  270. if(childData and childData.parent) then
  271. anyGrouped = true;
  272. break;
  273. end
  274. end
  275. if(anyGrouped) then
  276. menu[1].notClickable = 1;
  277. menu[1].text = "|cFF777777"..menu[1].text;
  278. menu[2].notClickable = 1;
  279. menu[2].text = "|cFF777777"..menu[2].text;
  280. end
  281. return menu;
  282. end
  283.  
  284. local valueFromPath = WeakAuras.ValueFromPath;
  285. local valueToPath = WeakAuras.ValueToPath;
  286.  
  287. -- This function computes the Levenshtein distance between two strings
  288. -- It is based on the Wagner-Fisher algorithm
  289. --
  290. -- The Levenshtein distance between two strings is the minimum number of operations needed
  291. -- to transform one into the other, with allowable operations being addition of one letter,
  292. -- subtraction of one letter, or substitution of one letter for another
  293. --
  294. -- It is used in this program to match spell icon textures with "good" spell names; i.e.,
  295. -- spell names that are very similar to the name of the texture
  296. local function Lev(str1, str2)
  297. local matrix = {};
  298. for i=0, str1:len() do
  299. matrix[i] = {[0] = i};
  300. end
  301. for j=0, str2:len() do
  302. matrix[0][j] = j;
  303. end
  304. for j=1, str2:len() do
  305. for i =1, str1:len() do
  306. if(str1:sub(i, i) == str2:sub(j, j)) then
  307. matrix[i][j] = matrix[i-1][j-1];
  308. else
  309. matrix[i][j] = math.min(matrix[i-1][j], matrix[i][j-1], matrix[i-1][j-1]) + 1;
  310. end
  311. end
  312. end
  313.  
  314. return matrix[str1:len()][str2:len()];
  315. end
  316.  
  317. local trigger_types = WeakAuras.trigger_types;
  318. local debuff_types = WeakAuras.debuff_types;
  319. local unit_types = WeakAuras.unit_types;
  320. local actual_unit_types = WeakAuras.actual_unit_types;
  321. local actual_unit_types_with_specific = WeakAuras.actual_unit_types_with_specific;
  322. local threat_unit_types = WeakAuras.threat_unit_types;
  323. local unit_threat_situations = WeakAuras.unit_threat_situations;
  324. local no_unit_threat_situations = WeakAuras.no_unit_threat_situations;
  325. local class_for_stance_types = WeakAuras.class_for_stance_types;
  326. local class_types = WeakAuras.class_types;
  327. local deathknight_form_types = WeakAuras.deathknight_form_types;
  328. local druid_form_types = WeakAuras.druid_form_types;
  329. local paladin_form_types = WeakAuras.paladin_form_types;
  330. local priest_form_types = WeakAuras.priest_form_types;
  331. local rogue_form_types = WeakAuras.rogue_form_types;
  332. local shaman_form_types = WeakAuras.shaman_form_types;
  333. local warrior_form_types = WeakAuras.warrior_form_types;
  334. local monk_form_types = WeakAuras.monk_form_types;
  335. local single_form_types = WeakAuras.single_form_types;
  336. local blend_types = WeakAuras.blend_types;
  337. local point_types = WeakAuras.point_types;
  338. local event_types = WeakAuras.event_types;
  339. local status_types = WeakAuras.status_types;
  340. local subevent_prefix_types = WeakAuras.subevent_prefix_types;
  341. local subevent_actual_prefix_types = WeakAuras.subevent_actual_prefix_types;
  342. local subevent_suffix_types = WeakAuras.subevent_suffix_types;
  343. local power_types = WeakAuras.power_types;
  344. local miss_types = WeakAuras.miss_types;
  345. local environmental_types = WeakAuras.environmental_types;
  346. local aura_types = WeakAuras.aura_types;
  347. local orientation_types = WeakAuras.orientation_types;
  348. local spec_types = WeakAuras.spec_types;
  349. local totem_types = WeakAuras.totem_types;
  350. local texture_types = WeakAuras.texture_types;
  351. local operator_types = WeakAuras.operator_types;
  352. local string_operator_types = WeakAuras.string_operator_types;
  353. local weapon_types = WeakAuras.weapon_types;
  354. local rune_specific_types = WeakAuras.rune_specific_types;
  355. local check_types = WeakAuras.check_types;
  356. local custom_trigger_types = WeakAuras.custom_trigger_types;
  357. local eventend_types = WeakAuras.eventend_types;
  358. local autoeventend_types = WeakAuras.autoeventend_types;
  359. local justify_types = WeakAuras.justify_types;
  360. local grow_types = WeakAuras.grow_types;
  361. local align_types = WeakAuras.align_types;
  362. local rotated_align_types = WeakAuras.rotated_align_types;
  363. local anim_types = WeakAuras.anim_types;
  364. local anim_translate_types = WeakAuras.anim_translate_types;
  365. local anim_scale_types = WeakAuras.anim_scale_types;
  366. local anim_alpha_types = WeakAuras.anim_alpha_types;
  367. local anim_rotate_types = WeakAuras.anim_rotate_types;
  368. local anim_color_types = WeakAuras.anim_color_types;
  369. local group_types = WeakAuras.group_types;
  370. local difficulty_types = WeakAuras.difficulty_types;
  371. local anim_start_preset_types = WeakAuras.anim_start_preset_types;
  372. local anim_main_preset_types = WeakAuras.anim_main_preset_types;
  373. local anim_finish_preset_types = WeakAuras.anim_finish_preset_types;
  374. local chat_message_types = WeakAuras.chat_message_types;
  375. local send_chat_message_types = WeakAuras.send_chat_message_types;
  376. local sound_types = WeakAuras.sound_types;
  377. local duration_types = WeakAuras.duration_types;
  378. local duration_types_no_choice = WeakAuras.duration_types_no_choice;
  379. local group_aura_name_info_types = WeakAuras.group_aura_name_info_types;
  380. local group_aura_stack_info_types = WeakAuras.group_aura_stack_info_types;
  381.  
  382. local function union(table1, table2)
  383. local meta = {};
  384. for i,v in pairs(table1) do
  385. meta[i] = v;
  386. end
  387. for i,v in pairs(table2) do
  388. meta[i] = v;
  389. end
  390. return meta;
  391. end
  392.  
  393. AceGUI:RegisterLayout("AbsoluteList", function(content, children)
  394. local yOffset = 0;
  395. for i = 1, #children do
  396. local child = children[i]
  397.  
  398. local frame = child.frame;
  399. frame:ClearAllPoints();
  400. frame:Show();
  401.  
  402. frame:SetPoint("LEFT", content);
  403. frame:SetPoint("RIGHT", content);
  404. frame:SetPoint("TOP", content, "TOP", 0, yOffset)
  405.  
  406. if child.DoLayout then
  407. child:DoLayout()
  408. end
  409.  
  410. yOffset = yOffset - ((frame.height or frame:GetHeight() or 0) + 2);
  411. end
  412. if(content.obj.LayoutFinished) then
  413. content.obj:LayoutFinished(nil, yOffset * -1);
  414. end
  415. end);
  416.  
  417. AceGUI:RegisterLayout("ButtonsScrollLayout", function(content, children)
  418. local yOffset = 0;
  419.  
  420. local scrollTop, scrollBottom = content.obj:GetScrollPos();
  421. for i = 1, #children do
  422. local child = children[i]
  423.  
  424. local frame = child.frame;
  425. local frameHeight = (frame.height or frame:GetHeight() or 0);
  426.  
  427. frame:ClearAllPoints();
  428. if (-yOffset + frameHeight > scrollTop and -yOffset - frameHeight < scrollBottom) then
  429. frame:Show();
  430.  
  431. frame:SetPoint("LEFT", content);
  432. frame:SetPoint("RIGHT", content);
  433. frame:SetPoint("TOP", content, "TOP", 0, yOffset)
  434. else
  435. frame:Hide();
  436. frame.yOffset = yOffset
  437. end
  438.  
  439. if child.DoLayout then
  440. child:DoLayout()
  441. end
  442.  
  443. yOffset = yOffset - (frameHeight + 2);
  444. end
  445. if(content.obj.LayoutFinished) then
  446. content.obj:LayoutFinished(nil, yOffset * -1);
  447. end
  448. end);
  449.  
  450. -- Builds a cache of name/icon pairs from existing spell data
  451. -- Why? Because if you call GetSpellInfo with a spell name, it only works if the spell is an actual castable ability,
  452. -- but if you call it with a spell id, you can get buffs, talents, etc. This is useful for displaying faux aura information
  453. -- for displays that are not actually connected to auras (for non-automatic icon displays with predefined icons)
  454. --
  455. -- This is a rather slow operation, so it's only done once, and the result is subsequently saved
  456. function WeakAuras.CreateIconCache(callback)
  457. local func = function()
  458. local id = 0;
  459. local misses = 0;
  460.  
  461. while (misses < 200) do
  462. id = id + 1;
  463. local name, _, icon = GetSpellInfo(id);
  464. if(name) then
  465. if not(iconCache[name]) then
  466. iconCache[name] = icon;
  467. end
  468. if not(idCache[name]) then
  469. idCache[name] = {}
  470. end
  471. idCache[name][id] = true;
  472. misses = 0;
  473. else
  474. misses = misses + 1;
  475. end
  476. coroutine.yield();
  477. end
  478.  
  479. if(callback) then
  480. callback();
  481. end
  482. end
  483.  
  484. local co = coroutine.create(func);
  485. dynFrame:AddAction(callback, co);
  486. end
  487.  
  488. function WeakAuras.ConstructOptions(prototype, data, startorder, subPrefix, subSuffix, triggernum, triggertype, unevent)
  489. local trigger, untrigger;
  490. if(triggertype == "load") then
  491. trigger = data.load;
  492. elseif(data.controlledChildren) then
  493. trigger, untrigger = {}, {};
  494. else
  495. if(triggernum == 0) then
  496. data.untrigger = data.untrigger or {};
  497. if(triggertype == "untrigger") then
  498. trigger = data.untrigger;
  499. else
  500. trigger = data.trigger;
  501. untrigger = data.untrigger;
  502. end
  503. elseif(triggernum >= 1) then
  504. data.additional_triggers[triggernum].untrigger = data.additional_triggers[triggernum].untrigger or {};
  505. if(triggertype == "untrigger") then
  506. trigger = data.additional_triggers[triggernum].untrigger;
  507. else
  508. trigger = data.additional_triggers[triggernum].trigger;
  509. untrigger = data.additional_triggers[triggernum].untrigger;
  510. end
  511. else
  512. error("Improper argument to WeakAuras.ConstructOptions - trigger number not in range");
  513. end
  514. end
  515. unevent = unevent or trigger.unevent;
  516. local options = {};
  517. local order = startorder or 10;
  518. for index, arg in pairs(prototype.args) do
  519. local hidden = nil;
  520. if(type(arg.enable) == "function") then
  521. hidden = function() return not arg.enable(trigger) end;
  522. end
  523. local name = arg.name;
  524. if(name and not arg.hidden) then
  525. local realname = name;
  526. if(triggertype == "untrigger") then
  527. name = "untrigger_"..name;
  528. end
  529. if(arg.type == "tristate") then
  530. options["use_"..name] = {
  531. type = "toggle",
  532. name = function(input)
  533. local value = trigger["use_"..realname];
  534. if(value == nil) then return arg.display;
  535. elseif(value == false) then return "|cFFFF0000 "..L["Negator"].." "..arg.display;
  536. else return "|cFF00FF00"..arg.display; end
  537. end,
  538. get = function()
  539. local value = trigger["use_"..realname];
  540. if(value == nil) then return false;
  541. elseif(value == false) then return "false";
  542. else return "true"; end
  543. end,
  544. set = function(info, v)
  545. if(v) then
  546. trigger["use_"..realname] = true;
  547. else
  548. local value = trigger["use_"..realname];
  549. if(value == false) then trigger["use_"..realname] = nil;
  550. else trigger["use_"..realname] = false end
  551. end
  552. WeakAuras.Add(data);
  553. WeakAuras.ScanForLoads();
  554. WeakAuras.SetThumbnail(data);
  555. WeakAuras.SetIconNames(data);
  556. WeakAuras.UpdateDisplayButton(data);
  557. WeakAuras.SortDisplayButtons();
  558. end,
  559. hidden = hidden,
  560. order = order
  561. };
  562. elseif(arg.type == "multiselect") then
  563. options["use_"..name] = {
  564. type = "toggle",
  565. name = arg.display,
  566. desc = function()
  567. local v = trigger["use_"..realname];
  568. if(v == true) then
  569. return L["Multiselect single tooltip"];
  570. elseif(v == false) then
  571. return L["Multiselect multiple tooltip"];
  572. else
  573. return L["Multiselect ignored tooltip"];
  574. end
  575. end,
  576. get = function()
  577. local value = trigger["use_"..realname];
  578. if(value == nil) then return false;
  579. elseif(value == false) then return "false";
  580. else return "true"; end
  581. end,
  582. set = function(info, v)
  583. if(v) then
  584. trigger["use_"..realname] = true;
  585. else
  586. local value = trigger["use_"..realname];
  587. if(value == false) then trigger["use_"..realname] = nil;
  588. else
  589. trigger["use_"..realname] = false
  590. if(trigger[realname].single) then
  591. trigger[realname].multi[trigger[realname].single] = true;
  592. end
  593. end
  594. end
  595. WeakAuras.Add(data);
  596. WeakAuras.ScanForLoads();
  597. WeakAuras.SetThumbnail(data);
  598. WeakAuras.SetIconNames(data);
  599. WeakAuras.UpdateDisplayButton(data);
  600. WeakAuras.SortDisplayButtons();
  601. end,
  602. hidden = hidden,
  603. order = order
  604. };
  605. else
  606. options["use_"..name] = {
  607. type = "toggle",
  608. name = arg.display,
  609. order = order,
  610. hidden = hidden,
  611. get = function() return trigger["use_"..realname]; end,
  612. set = function(info, v)
  613. trigger["use_"..realname] = v;
  614. WeakAuras.Add(data);
  615. WeakAuras.ScanForLoads();
  616. WeakAuras.SetThumbnail(data);
  617. WeakAuras.SetIconNames(data);
  618. WeakAuras.UpdateDisplayButton(data);
  619. WeakAuras.SortDisplayButtons();
  620. end
  621. };
  622. end
  623. if(arg.type == "toggle" or arg.type == "tristate") then
  624. options["use_"..name].width = arg.width or "double";
  625. end
  626. if(arg.required) then
  627. trigger["use_"..realname] = true;
  628. if not(triggertype) then
  629. options["use_"..name].disabled = true;
  630. else
  631. options["use_"..name] = nil;
  632. order = order - 1;
  633. end
  634. end
  635. order = order + 1;
  636. if(arg.type == "number") then
  637. options[name.."_operator"] = {
  638. type = "select",
  639. name = L["Operator"],
  640. width = "half",
  641. order = order,
  642. hidden = hidden,
  643. values = operator_types,
  644. disabled = function() return not trigger["use_"..realname]; end,
  645. get = function() return trigger["use_"..realname] and trigger[realname.."_operator"] or nil; end,
  646. set = function(info, v)
  647. trigger[realname.."_operator"] = v;
  648. WeakAuras.Add(data);
  649. WeakAuras.ScanForLoads();
  650. WeakAuras.SetThumbnail(data);
  651. WeakAuras.SetIconNames(data);
  652. WeakAuras.UpdateDisplayButton(data);
  653. WeakAuras.SortDisplayButtons();
  654. end
  655. };
  656. if(arg.required and not triggertype) then
  657. options[name.."_operator"].set = function(info, v) trigger[realname.."_operator"] = v; untrigger[realname.."_operator"] = v; WeakAuras.Add(data); WeakAuras.ScanForLoads(); WeakAuras.SortDisplayButtons(); end
  658. elseif(arg.required and triggertype == "untrigger") then
  659. options[name.."_operator"] = nil;
  660. order = order - 1;
  661. end
  662. order = order + 1;
  663. options[name] = {
  664. type = "input",
  665. validate = ValidateNumeric,
  666. name = arg.display,
  667. width = "half",
  668. order = order,
  669. hidden = hidden,
  670. disabled = function() return not trigger["use_"..realname]; end,
  671. get = function() return trigger["use_"..realname] and trigger[realname] or nil; end,
  672. set = function(info, v)
  673. trigger[realname] = v;
  674. WeakAuras.Add(data);
  675. WeakAuras.ScanForLoads();
  676. WeakAuras.SetThumbnail(data);
  677. WeakAuras.SetIconNames(data);
  678. WeakAuras.UpdateDisplayButton(data);
  679. WeakAuras.SortDisplayButtons();
  680. end
  681. };
  682. if(arg.required and not triggertype) then
  683. options[name].set = function(info, v) trigger[realname] = v; untrigger[realname] = v; WeakAuras.Add(data); WeakAuras.ScanForLoads(); WeakAuras.SortDisplayButtons(); end
  684. elseif(arg.required and triggertype == "untrigger") then
  685. options[name] = nil;
  686. order = order - 1;
  687. end
  688. order = order + 1;
  689. elseif(arg.type == "string") then
  690. options[name] = {
  691. type = "input",
  692. name = arg.display,
  693. order = order,
  694. hidden = hidden,
  695. disabled = function() return not trigger["use_"..realname]; end,
  696. get = function() return trigger["use_"..realname] and trigger[realname] or nil; end,
  697. set = function(info, v)
  698. trigger[realname] = v;
  699. WeakAuras.Add(data);
  700. WeakAuras.ScanForLoads();
  701. WeakAuras.SetThumbnail(data);
  702. WeakAuras.SetIconNames(data);
  703. WeakAuras.UpdateDisplayButton(data);
  704. WeakAuras.SortDisplayButtons();
  705. end
  706. };
  707. if(arg.required and not triggertype) then
  708. options[name].set = function(info, v) trigger[realname] = v; untrigger[realname] = v; WeakAuras.Add(data); WeakAuras.ScanForLoads(); WeakAuras.SortDisplayButtons(); end
  709. elseif(arg.required and triggertype == "untrigger") then
  710. options[name] = nil;
  711. order = order - 1;
  712. end
  713. order = order + 1;
  714. elseif(arg.type == "longstring") then
  715. options[name.."_operator"] = {
  716. type = "select",
  717. name = L["Operator"],
  718. order = order,
  719. hidden = hidden,
  720. values = string_operator_types,
  721. disabled = function() return not trigger["use_"..realname]; end,
  722. get = function() return trigger["use_"..realname] and trigger[realname.."_operator"] or nil; end,
  723. set = function(info, v)
  724. trigger[realname.."_operator"] = v;
  725. WeakAuras.Add(data);
  726. WeakAuras.ScanForLoads();
  727. WeakAuras.SetThumbnail(data);
  728. WeakAuras.SetIconNames(data);
  729. WeakAuras.UpdateDisplayButton(data);
  730. WeakAuras.SortDisplayButtons();
  731. end
  732. };
  733. if(arg.required and not triggertype) then
  734. options[name.."_operator"].set = function(info, v) trigger[realname.."_operator"] = v; untrigger[realname.."_operator"] = v; WeakAuras.Add(data); WeakAuras.ScanForLoads(); WeakAuras.SortDisplayButtons(); end
  735. elseif(arg.required and triggertype == "untrigger") then
  736. options[name.."_operator"] = nil;
  737. order = order - 1;
  738. end
  739. order = order + 1;
  740. options[name] = {
  741. type = "input",
  742. name = arg.display,
  743. width = "double",
  744. order = order,
  745. hidden = hidden,
  746. disabled = function() return not trigger["use_"..realname]; end,
  747. get = function() return trigger["use_"..realname] and trigger[realname] or nil; end,
  748. set = function(info, v)
  749. trigger[realname] = v;
  750. WeakAuras.Add(data);
  751. WeakAuras.ScanForLoads();
  752. WeakAuras.SetThumbnail(data);
  753. WeakAuras.SetIconNames(data);
  754. WeakAuras.UpdateDisplayButton(data);
  755. WeakAuras.SortDisplayButtons();
  756. end
  757. };
  758. if(arg.required and not triggertype) then
  759. options[name].set = function(info, v) trigger[realname] = v; untrigger[realname] = v; WeakAuras.Add(data); WeakAuras.ScanForLoads(); WeakAuras.SortDisplayButtons(); end
  760. elseif(arg.required and triggertype == "untrigger") then
  761. options[name] = nil;
  762. order = order - 1;
  763. end
  764. order = order + 1;
  765. elseif(arg.type == "spell" or arg.type == "aura" or arg.type == "item") then
  766. options["icon"..name] = {
  767. type = "execute",
  768. name = "",
  769. order = order,
  770. hidden = hidden,
  771. width = "normal",
  772. image = function()
  773. if(trigger["use_"..realname] and trigger[realname]) then
  774. if(arg.type == "aura") then
  775. return iconCache[trigger[realname]] or "", 18, 18;
  776. elseif(arg.type == "spell") then
  777. local _, _, icon = GetSpellInfo(trigger[realname]);
  778. return icon or "", 18, 18;
  779. elseif(arg.type == "item") then
  780. local _, _, _, _, _, _, _, _, _, icon = GetItemInfo(trigger[realname]);
  781. return icon or "", 18, 18;
  782. end
  783. else
  784. return "", 18, 18;
  785. end
  786. end,
  787. disabled = function() return not ((arg.type == "aura" and trigger[realname] and iconCache[trigger[realname]]) or (arg.type == "spell" and trigger[realname] and GetSpellInfo(trigger[realname])) or (arg.type == "item" and trigger[realname] and GetItemIcon(trigger[realname]))) end
  788. };
  789. order = order + 1;
  790. options[name] = {
  791. type = "input",
  792. name = arg.display,
  793. order = order,
  794. hidden = hidden,
  795. width = "double",
  796. disabled = function() return not trigger["use_"..realname]; end,
  797. get = function()
  798. if(arg.type == "item") then
  799. if(trigger["use_"..realname] and trigger[realname] and trigger[realname] ~= "") then
  800. local name = GetItemInfo(trigger[realname]);
  801. if(name) then
  802. return name;
  803. else
  804. return "Invalid Item Name/ID/Link";
  805. end
  806. else
  807. return nil;
  808. end
  809. elseif(arg.type == "spell") then
  810. if(trigger["use_"..realname] and trigger[realname] and trigger[realname] ~= "") then
  811. local name = GetSpellInfo(trigger[realname]);
  812. if(name) then
  813. return name;
  814. else
  815. return "Invalid Spell Name/ID/Link";
  816. end
  817. else
  818. return nil;
  819. end
  820. else
  821. return trigger["use_"..realname] and trigger[realname] or nil;
  822. end
  823. end,
  824. set = function(info, v)
  825. local fixedInput = v;
  826. if(arg.type == "aura") then
  827. fixedInput = WeakAuras.CorrectAuraName(v);
  828. elseif(arg.type == "spell") then
  829. fixedInput = WeakAuras.CorrectSpellName(v);
  830. elseif(arg.type == "item") then
  831. fixedInput = WeakAuras.CorrectItemName(v);
  832. end
  833. trigger[realname] = fixedInput;
  834. WeakAuras.Add(data);
  835. WeakAuras.ScanForLoads();
  836. WeakAuras.SetThumbnail(data);
  837. WeakAuras.SetIconNames(data);
  838. WeakAuras.UpdateDisplayButton(data);
  839. WeakAuras.SortDisplayButtons();
  840. end
  841. };
  842. if(arg.required and not triggertype) then
  843. options[name].set = function(info, v)
  844. local fixedInput = v;
  845. if(arg.type == "aura") then
  846. fixedInput = WeakAuras.CorrectAuraName(v);
  847. elseif(arg.type == "spell") then
  848. fixedInput = WeakAuras.CorrectSpellName(v);
  849. elseif(arg.type == "item") then
  850. fixedInput = WeakAuras.CorrectItemName(v);
  851. end
  852. trigger[realname] = fixedInput;
  853. untrigger[realname] = fixedInput;
  854. WeakAuras.Add(data);
  855. WeakAuras.ScanForLoads();
  856. WeakAuras.SetThumbnail(data);
  857. WeakAuras.SetIconNames(data);
  858. WeakAuras.UpdateDisplayButton(data);
  859. WeakAuras.SortDisplayButtons();
  860. end
  861. elseif(arg.required and triggertype == "untrigger") then
  862. options["icon"..name] = nil;
  863. options[name] = nil;
  864. order = order - 2;
  865. end
  866. order = order + 1;
  867. elseif(arg.type == "select" or arg.type == "unit") then
  868. local values;
  869. if(type(arg.values) == "function") then
  870. values = arg.values(trigger);
  871. else
  872. values = WeakAuras[arg.values];
  873. end
  874. options[name] = {
  875. type = "select",
  876. name = arg.display,
  877. order = order,
  878. hidden = hidden,
  879. values = values,
  880. disabled = function() return not trigger["use_"..realname]; end,
  881. get = function()
  882. if(arg.type == "unit" and trigger["use_specific_"..realname]) then
  883. return "member";
  884. end
  885. return trigger["use_"..realname] and trigger[realname] or nil;
  886. end,
  887. set = function(info, v)
  888. trigger[realname] = v;
  889. if(arg.type == "unit" and v == "member") then
  890. trigger["use_specific_"..realname] = true;
  891. trigger[realname] = UnitName("player");
  892. else
  893. trigger["use_specific_"..realname] = nil;
  894. end
  895. WeakAuras.Add(data);
  896. WeakAuras.ScanForLoads();
  897. WeakAuras.SetThumbnail(data);
  898. WeakAuras.SetIconNames(data);
  899. WeakAuras.UpdateDisplayButton(data);
  900. WeakAuras.SortDisplayButtons();
  901. end
  902. };
  903. if(arg.required and not triggertype) then
  904. options[name].set = function(info, v)
  905. trigger[realname] = v;
  906. if(arg.type == "unit" and v == "member") then
  907. trigger["use_specific_"..realname] = true;
  908. else
  909. trigger["use_specific_"..realname] = nil;
  910. end
  911. untrigger[realname] = v;
  912. if(arg.type == "unit" and v == "member") then
  913. untrigger["use_specific_"..realname] = true;
  914. else
  915. untrigger["use_specific_"..realname] = nil;
  916. end
  917. WeakAuras.Add(data);
  918. WeakAuras.ScanForLoads();
  919. WeakAuras.SetThumbnail(data);
  920. WeakAuras.SetIconNames(data);
  921. WeakAuras.UpdateDisplayButton(data);
  922. WeakAuras.SortDisplayButtons();
  923. end
  924. elseif(arg.required and triggertype == "untrigger") then
  925. options[name] = nil;
  926. order = order - 1;
  927. end
  928. order = order + 1;
  929. if(arg.type == "unit" and not (arg.required and triggertype == "untrigger")) then
  930. options["use_specific_"..name] = {
  931. type = "toggle",
  932. name = L["Specific Unit"],
  933. order = order,
  934. hidden = function() return (not trigger["use_specific_"..realname]) or (type(hidden) == "function" and hidden() or hidden) end,
  935. get = function() return true end,
  936. set = function(info, v)
  937. trigger["use_specific_"..realname] = nil;
  938. options[name].set(info, "player");
  939. end
  940. }
  941. order = order + 1;
  942. options["specific_"..name] = {
  943. type = "input",
  944. name = L["Specific Unit"],
  945. desc = L["Can be a name or a UID (e.g., party1). Only works on friendly players in your group."],
  946. order = order,
  947. hidden = function() return (not trigger["use_specific_"..realname]) or (type(hidden) == "function" and hidden() or hidden) end,
  948. get = function() return trigger[realname] end,
  949. set = function(info, v)
  950. trigger[realname] = v;
  951. if(arg.required and not triggertype) then
  952. untrigger[realname] = v;
  953. end
  954. WeakAuras.Add(data);
  955. end
  956. };
  957. order = order + 1;
  958. end
  959. elseif(arg.type == "multiselect") then
  960. local values;
  961. if(type(arg.values) == "function") then
  962. values = arg.values(trigger);
  963. else
  964. values = WeakAuras[arg.values];
  965. end
  966. options[name] = {
  967. type = "select",
  968. name = arg.display,
  969. order = order,
  970. values = values,
  971. hidden = function() return hidden or trigger["use_"..realname] == false; end,
  972. disabled = function() return not trigger["use_"..realname]; end,
  973. get = function() return trigger["use_"..realname] and trigger[realname] and trigger[realname].single or nil; end,
  974. set = function(info, v)
  975. trigger[realname].single = v;
  976. WeakAuras.Add(data);
  977. WeakAuras.ScanForLoads();
  978. WeakAuras.SetThumbnail(data);
  979. WeakAuras.SetIconNames(data);
  980. WeakAuras.UpdateDisplayButton(data);
  981. WeakAuras.SortDisplayButtons();
  982. end
  983. };
  984. if(arg.required and not triggertype) then
  985. options[name].set = function(info, v)
  986. trigger[realname].single = v;
  987. untrigger[realname].single = v;
  988. WeakAuras.Add(data);
  989. WeakAuras.ScanForLoads();
  990. WeakAuras.SetThumbnail(data);
  991. WeakAuras.SetIconNames(data);
  992. WeakAuras.UpdateDisplayButton(data);
  993. WeakAuras.SortDisplayButtons();
  994. end
  995. end
  996.  
  997. options["multiselect_"..name] = {
  998. type = "multiselect",
  999. name = arg.display,
  1000. order = order,
  1001. hidden = function() return hidden or trigger["use_"..realname] ~= false; end,
  1002. values = values,
  1003. -- width = "half",
  1004. get = function(info, v)
  1005. if(trigger["use_"..realname] == false and trigger[realname] and trigger[realname].multi) then
  1006. return trigger[realname].multi[v];
  1007. end
  1008. end,
  1009. set = function(info, v)
  1010. if(trigger[realname].multi[v]) then
  1011. trigger[realname].multi[v] = nil;
  1012. else
  1013. trigger[realname].multi[v] = true;
  1014. end
  1015. WeakAuras.Add(data);
  1016. WeakAuras.ScanForLoads();
  1017. WeakAuras.SetThumbnail(data);
  1018. WeakAuras.SetIconNames(data);
  1019. WeakAuras.UpdateDisplayButton(data);
  1020. WeakAuras.SortDisplayButtons();
  1021. end
  1022. };
  1023. options["multiselectspace_"..name] = {
  1024. type = "execute",
  1025. name = "",
  1026. order = (order - 0.5),
  1027. hidden = function() return hidden or trigger["use_"..realname] ~= false; end,
  1028. disabled = true,
  1029. image = function() return "", 52, 52 end
  1030. };
  1031. if(arg.required and not triggertype) then
  1032. options[name].set = function(info, v)
  1033. if(trigger[realname].multi[v]) then
  1034. trigger[realname].multi[v] = nil;
  1035. else
  1036. trigger[realname].multi[v] = true;
  1037. end
  1038. if(untrigger[realname].multi[v]) then
  1039. untrigger[realname].multi[v] = nil;
  1040. else
  1041. untrigger[realname].multi[v] = true;
  1042. end
  1043. WeakAuras.Add(data);
  1044. WeakAuras.ScanForLoads();
  1045. WeakAuras.SetThumbnail(data);
  1046. WeakAuras.SetIconNames(data);
  1047. WeakAuras.UpdateDisplayButton(data);
  1048. WeakAuras.SortDisplayButtons();
  1049. end
  1050. end
  1051.  
  1052. if(arg.required and triggertype == "untrigger") then
  1053. options[name] = nil;
  1054. options["multiselect_"..name] = nil;
  1055. else
  1056. order = order + 1;
  1057. end
  1058. end
  1059. end
  1060. end
  1061.  
  1062. if not(triggertype or prototype.automaticrequired) then
  1063. options.unevent = {
  1064. type = "select",
  1065. name = L["Hide"],
  1066. width = "double",
  1067. order = order
  1068. };
  1069. order = order + 1;
  1070. if(unevent == "timed") then
  1071. options.unevent.width = "normal";
  1072. options.duration = {
  1073. type = "input",
  1074. name = L["Duration (s)"],
  1075. order = order
  1076. }
  1077. order = order + 1;
  1078. else
  1079. options.unevent.width = "double";
  1080. end
  1081. if(unevent == "custom") then
  1082. local unevent_options = WeakAuras.ConstructOptions(prototype, data, order, subPrefix, subSuffix, triggernum, "untrigger");
  1083. options = union(options, unevent_options);
  1084. end
  1085. if(prototype.automatic) then
  1086. options.unevent.values = autoeventend_types;
  1087. else
  1088. options.unevent.values = eventend_types;
  1089. end
  1090. end
  1091.  
  1092. WeakAuras.option = options;
  1093. return options;
  1094. end
  1095.  
  1096. local frame;
  1097.  
  1098. local db;
  1099. local odb;
  1100. local options;
  1101. local newOptions;
  1102. local loadedOptions;
  1103. local unloadedOptions;
  1104. local pickonupdate;
  1105. local loadedFrame = CreateFrame("FRAME");
  1106. loadedFrame:RegisterEvent("ADDON_LOADED");
  1107. loadedFrame:SetScript("OnEvent", function(self, event, addon)
  1108. if (event == "ADDON_LOADED") then
  1109. if(addon == ADDON_NAME) then
  1110. db = WeakAurasSaved;
  1111. WeakAurasOptionsSaved = WeakAurasOptionsSaved or {};
  1112.  
  1113. odb = WeakAurasOptionsSaved;
  1114.  
  1115. odb.iconCache = odb.iconCache or {};
  1116. iconCache = odb.iconCache;
  1117. odb.idCache = odb.idCache or {};
  1118. idCache = odb.idCache;
  1119. odb.talentCache = odb.talentCache or {};
  1120.  
  1121. local _, build = GetBuildInfo();
  1122. local locale = GetLocale();
  1123. local version = WeakAuras.versionString
  1124.  
  1125. local num = 0;
  1126. for i,v in pairs(odb.iconCache) do
  1127. num = num + 1;
  1128. end
  1129.  
  1130. if(num < 39000 or odb.locale ~= locale or odb.build ~= build or odb.version ~= version) then
  1131. WeakAuras.CreateIconCache();
  1132.  
  1133. odb.build = build;
  1134. odb.locale = locale;
  1135. odb.version = version;
  1136. end
  1137.  
  1138. -- Updates the icon cache with whatever icons WeakAuras core has actually used.
  1139. -- This helps keep name<->icon matches relevant.
  1140. for name, icon in pairs(db.tempIconCache) do
  1141. iconCache[name] = icon;
  1142. end
  1143.  
  1144. --Saves the talent names and icons for the current class
  1145. --Used for making the Talent Selected load option prettier
  1146.  
  1147. end
  1148. end
  1149. end);
  1150.  
  1151. function WeakAuras.DeleteOption(data)
  1152. local id = data.id;
  1153. local parentData;
  1154. if(data.parent) then
  1155. parentData = db.displays[data.parent];
  1156. end
  1157.  
  1158. if(data.controlledChildren) then
  1159. for index, childId in pairs(data.controlledChildren) do
  1160. local childButton = displayButtons[childId];
  1161. if(childButton) then
  1162. childButton:SetGroup();
  1163. end
  1164. local childData = db.displays[childId];
  1165. if(childData) then
  1166. childData.parent = nil;
  1167. end
  1168. end
  1169. end
  1170.  
  1171. WeakAuras.HideAllClones(id);
  1172.  
  1173. WeakAuras.Delete(data);
  1174. frame:ClearPicks();
  1175. frame.buttonsScroll:DeleteChild(displayButtons[id]);
  1176. thumbnails[id].region:Hide();
  1177. thumbnails[id] = nil;
  1178. displayButtons[id] = nil;
  1179.  
  1180. if(parentData and parentData.controlledChildren) then
  1181. for index, childId in pairs(parentData.controlledChildren) do
  1182. local childButton = displayButtons[childId];
  1183. if(childButton) then
  1184. childButton:SetGroupOrder(index, #parentData.controlledChildren);
  1185. end
  1186. end
  1187. WeakAuras.Add(parentData);
  1188. WeakAuras.ReloadGroupRegionOptions(parentData);
  1189. WeakAuras.UpdateDisplayButton(parentData);
  1190. end
  1191. end
  1192.  
  1193. function WeakAuras.OptionsFrame()
  1194. if(frame) then
  1195. return frame;
  1196. else
  1197. return nil;
  1198. end
  1199. end
  1200.  
  1201. function WeakAuras.ToggleOptions(msg)
  1202. if(frame and frame:IsVisible()) then
  1203. WeakAuras.HideOptions();
  1204. else
  1205. WeakAuras.ShowOptions(msg);
  1206. end
  1207. end
  1208.  
  1209. function WeakAuras.UpdateCloneConfig(data)
  1210. if(WeakAuras.CanHaveClones(data)) then
  1211. local cloneRegion = WeakAuras.EnsureClone(data.id, 1);
  1212. cloneRegion:Expand();
  1213.  
  1214. cloneRegion = WeakAuras.EnsureClone(data.id, 2);
  1215. cloneRegion:Expand();
  1216.  
  1217. --if(data.parent and WeakAuras.regions[data.parent]) then
  1218. if(data.parent and WeakAuras.regions[data.parent] and
  1219. WeakAuras.regions[data.parent].region and
  1220. WeakAuras.regions[data.parent].region.ControlChildren) then
  1221. WeakAuras.regions[data.parent].region:ControlChildren();
  1222. end
  1223.  
  1224. WeakAuras.SetIconNames(data);
  1225. end
  1226. end
  1227.  
  1228. function WeakAuras.ShowOptions(msg)
  1229. local firstLoad = not(frame);
  1230. WeakAuras.Pause();
  1231.  
  1232. if (firstLoad) then
  1233. frame = WeakAuras.CreateFrame();
  1234. frame.buttonsScroll.frame:Show();
  1235. WeakAuras.AddOption(tempGroup.id, tempGroup);
  1236. WeakAuras.LayoutDisplayButtons(msg);
  1237. end
  1238. frame.buttonsScroll.frame:Show();
  1239. WeakAuras.LockUpdateInfo();
  1240.  
  1241. frame:Show();
  1242. frame:PickOption("New");
  1243. if not(firstLoad) then
  1244. for id, button in pairs(displayButtons) do
  1245. if(loaded[id] ~= nil) then
  1246. button:PriorityShow(1);
  1247. end
  1248. end
  1249. end
  1250. end
  1251.  
  1252. function WeakAuras.HideOptions()
  1253. -- dynFrame:SetScript("OnUpdate", nil);
  1254. WeakAuras.UnlockUpdateInfo();
  1255.  
  1256. for id, data in pairs(db.displays) do
  1257. local region = WeakAuras.regions[id] and WeakAuras.regions[id].region;
  1258. if(region) then
  1259. region:SetScript("OnShow", nil);
  1260. region:SetScript("OnHide", nil);
  1261. end
  1262. end
  1263.  
  1264. if(frame) then
  1265. frame:Hide();
  1266. end
  1267.  
  1268. local tutFrame = WeakAuras.TutorialsFrame and WeakAuras.TutorialsFrame();
  1269. if(tutFrame and tutFrame:IsVisible()) then
  1270. tutFrame:Hide();
  1271. end
  1272.  
  1273. for id, data in pairs(WeakAuras.regions) do
  1274. data.region:Collapse();
  1275. end
  1276. WeakAuras.ReloadAll();
  1277. WeakAuras.Resume();
  1278. end
  1279.  
  1280. function WeakAuras.IsOptionsOpen()
  1281. if(frame and frame:IsVisible()) then
  1282. return true;
  1283. else
  1284. return false;
  1285. end
  1286. end
  1287.  
  1288. function WeakAuras.DoConfigUpdate()
  1289. local function GiveDynamicInfo(id, region, data, cloneNum)
  1290. if(WeakAuras.CanHaveDuration(data) == "timed") then
  1291. local rem = GetTime() + 8 - (frame.count + frame.elapsed);
  1292. if(cloneNum) then
  1293. rem = rem + (cloneNum == 1 and (frame.count >= 1 and 1 or -3) or (frame.count >= 2 and 2 or -2));
  1294. end
  1295. if(region.SetDurationInfo) then
  1296. if not(frame.count ~= 0 and region.cooldown and region.cooldown:IsVisible()) then
  1297. region:SetDurationInfo(12, rem);
  1298. end
  1299. end
  1300. WeakAuras.duration_cache:SetDurationInfo(id, 12, rem, nil, nil, cloneNum);
  1301. elseif(type(WeakAuras.CanHaveDuration(data)) == "table") then
  1302. local demoValues = WeakAuras.CanHaveDuration(data);
  1303. local current, maximum = demoValues.current or 10, demoValues.maximum or 100;
  1304. if(region.SetDurationInfo) then
  1305. region:SetDurationInfo(current, maximum, true);
  1306. end
  1307. WeakAuras.duration_cache:SetDurationInfo(id, current, maximum, nil, nil, cloneNum);
  1308. else
  1309. if(region.SetDurationInfo) then
  1310. region:SetDurationInfo(0, math.huge);
  1311. end
  1312. WeakAuras.duration_cache:SetDurationInfo(id, 0, math.huge, nil, nil, cloneNum);
  1313. end
  1314. end
  1315.  
  1316. for id, region in pairs(WeakAuras.regions) do
  1317. local data = db.displays[id];
  1318. if(data) then
  1319. GiveDynamicInfo(id, region.region, data);
  1320.  
  1321. if(WeakAuras.clones[id]) then
  1322. for cloneNum, cloneRegion in pairs(WeakAuras.clones[id]) do
  1323. GiveDynamicInfo(id, cloneRegion, data, cloneNum);
  1324. end
  1325. end
  1326. end
  1327. end
  1328. end
  1329.  
  1330. function WeakAuras.LockUpdateInfo()
  1331. frame.elapsed = 12;
  1332. frame.count = 0;
  1333. frame:SetScript("OnUpdate", function(self, elapsed)
  1334. frame.elapsed = frame.elapsed + elapsed;
  1335. if(frame.elapsed > 1) then
  1336. frame.elapsed = frame.elapsed - 1;
  1337. frame.count = (frame.count + 1) % 4;
  1338. WeakAuras.DoConfigUpdate();
  1339. end
  1340. end);
  1341. end
  1342.  
  1343. function WeakAuras.UnlockUpdateInfo()
  1344. frame:SetScript("OnUpdate", nil);
  1345. end
  1346.  
  1347. function WeakAuras.SetIconNames(data)
  1348. WeakAuras.SetIconName(data, WeakAuras.regions[data.id].region);
  1349. WeakAuras.SetIconName(data, thumbnails[data.id].region);
  1350. if(WeakAuras.clones[data.id]) then
  1351. for index, cloneRegion in pairs(WeakAuras.clones[data.id]) do
  1352. WeakAuras.SetIconName(data, cloneRegion);
  1353. end
  1354. end
  1355. end
  1356.  
  1357. function WeakAuras.SetIconName(data, region)
  1358. local name, icon;
  1359. if(data.trigger.type == "aura" and not (data.trigger.inverse or WeakAuras.CanGroupShowWithZero(data))) then
  1360. -- Try to get an icon from the icon cache
  1361. for index, checkname in pairs(data.trigger.names) do
  1362. if(iconCache[checkname]) then
  1363. name, icon = checkname, iconCache[checkname];
  1364. break;
  1365. end
  1366. end
  1367. elseif((data.trigger.type == "event" or data.trigger.type == "status") and data.trigger.event and WeakAuras.event_prototypes[data.trigger.event]) then
  1368. if(WeakAuras.event_prototypes[data.trigger.event].iconFunc) then
  1369. icon = WeakAuras.event_prototypes[data.trigger.event].iconFunc(data.trigger);
  1370. end
  1371. if(WeakAuras.event_prototypes[data.trigger.event].nameFunc) then
  1372. name = WeakAuras.event_prototypes[data.trigger.event].nameFunc(data.trigger);
  1373. end
  1374. end
  1375.  
  1376. WeakAuras.transmitCache[data.id] = icon;
  1377.  
  1378. if(region.SetIcon) then
  1379. region:SetIcon(icon);
  1380. end
  1381. if(region.SetName) then
  1382. region:SetName(name);
  1383. end
  1384. end
  1385.  
  1386. function WeakAuras.GetSortedOptionsLists()
  1387. local loadedSorted, unloadedSorted = {}, {};
  1388. local to_sort = {};
  1389. for id, data in pairs(db.displays) do
  1390. if(data.parent) then
  1391. -- Do nothing; children will be added later
  1392. elseif(loaded[id]) then
  1393. tinsert(to_sort, id);
  1394. end
  1395. end
  1396. table.sort(to_sort, function(a, b) return a < b end);
  1397. for _, id in ipairs(to_sort) do
  1398. tinsert(loadedSorted, id);
  1399. local data = WeakAuras.GetData(id);
  1400. local controlledChildren = data.controlledChildren;
  1401. if(controlledChildren) then
  1402. for _, childId in pairs(controlledChildren) do
  1403. tinsert(loadedSorted, childId);
  1404. end
  1405. end
  1406. end
  1407.  
  1408. wipe(to_sort);
  1409. for id, data in pairs(db.displays) do
  1410. if(data.parent) then
  1411. -- Do nothing; children will be added later
  1412. elseif not(loaded[id]) then
  1413. tinsert(to_sort, id);
  1414. end
  1415. end
  1416. table.sort(to_sort, function(a, b) return a < b end);
  1417. for _, id in ipairs(to_sort) do
  1418. tinsert(unloadedSorted, id);
  1419. local data = WeakAuras.GetData(id);
  1420. local controlledChildren = data.controlledChildren;
  1421. if(controlledChildren) then
  1422. for _, childId in pairs(controlledChildren) do
  1423. tinsert(unloadedSorted, childId);
  1424. end
  1425. end
  1426. end
  1427.  
  1428. return loadedSorted, unloadedSorted;
  1429. end
  1430.  
  1431. function WeakAuras.BuildOptions(list, callback)
  1432. frame.loadProgress:Show();
  1433. frame.filterInput:Hide();
  1434. frame.filterInputClear:Hide();
  1435.  
  1436. local total = 0;
  1437. for _,_ in pairs(list) do
  1438. total = total + 1;
  1439. end
  1440.  
  1441. local func = function()
  1442. local num = 0;
  1443. for id, data in pairs(list) do
  1444. if(data) then
  1445. if not(data.regionType == "group" or data.regionType == "dynamicgroup") then
  1446. WeakAuras.AddOption(id, data);
  1447. num = num + 1;
  1448. end
  1449. end
  1450. frame.loadProgress:SetText(L["Creating options: "]..num.."/"..total);
  1451.  
  1452. coroutine.yield();
  1453. end
  1454.  
  1455. callback();
  1456. frame.loadProgress:Hide();
  1457. frame.filterInput:Show();
  1458. frame.filterInputClear:Show();
  1459. end
  1460.  
  1461. local co = coroutine.create(func);
  1462. dynFrame:AddAction("BuildOptions", co);
  1463. end
  1464.  
  1465. function WeakAuras.LayoutDisplayButtons(msg)
  1466. local total = 0;
  1467. for _,_ in pairs(db.displays) do
  1468. total = total + 1;
  1469. end
  1470.  
  1471. local loadedSorted, unloadedSorted = WeakAuras.GetSortedOptionsLists();
  1472.  
  1473. frame.loadProgress:Show();
  1474. frame.buttonsScroll:AddChild(frame.newButton);
  1475. if(frame.addonsButton) then
  1476. frame.buttonsScroll:AddChild(frame.addonsButton);
  1477. end
  1478. frame.buttonsScroll:AddChild(frame.loadedButton);
  1479. frame.buttonsScroll:AddChild(frame.unloadedButton);
  1480.  
  1481. local func2 = function()
  1482. local num = frame.loadProgressNum or 0;
  1483. for index, id in pairs(unloadedSorted) do
  1484. local data = WeakAuras.GetData(id);
  1485. if(data) then
  1486. WeakAuras.EnsureDisplayButton(data);
  1487. WeakAuras.UpdateDisplayButton(data);
  1488.  
  1489. frame.buttonsScroll:AddChild(displayButtons[data.id]);
  1490. WeakAuras.SetIconNames(data);
  1491. if(WeakAuras.regions[data.id].region.SetStacks) then
  1492. WeakAuras.regions[data.id].region:SetStacks(1);
  1493. end
  1494.  
  1495. if (num % 50 == 0) then
  1496. frame.buttonsScroll:ResumeLayout()
  1497. frame.buttonsScroll:PerformLayout()
  1498. frame.buttonsScroll:PauseLayout()
  1499. end
  1500.  
  1501. num = num + 1;
  1502. end
  1503. frame.loadProgress:SetText(L["Creating buttons: "]..num.."/"..total);
  1504. frame.loadProgressNum = num;
  1505. coroutine.yield();
  1506. end
  1507.  
  1508. frame.buttonsScroll:ResumeLayout()
  1509. frame.buttonsScroll:PerformLayout()
  1510. WeakAuras.SortDisplayButtons(msg);
  1511.  
  1512. for id, button in pairs(displayButtons) do
  1513. if(loaded[id] ~= nil) then
  1514. button:PriorityShow(1);
  1515. end
  1516. end
  1517.  
  1518. frame.loadProgress:Hide();
  1519. frame.filterInput:Show();
  1520. frame.filterInputClear:Show();
  1521. end
  1522.  
  1523. local func1 = function()
  1524. local num = frame.loadProgressNum or 0;
  1525. frame.buttonsScroll:PauseLayout()
  1526. for index, id in pairs(loadedSorted) do
  1527. local data = WeakAuras.GetData(id);
  1528. if(data) then
  1529. WeakAuras.EnsureDisplayButton(data);
  1530. WeakAuras.UpdateDisplayButton(data);
  1531.  
  1532. local button = displayButtons[data.id]
  1533. frame.buttonsScroll:AddChild(button);
  1534. WeakAuras.SetIconNames(data);
  1535. if(WeakAuras.regions[data.id].region.SetStacks) then
  1536. WeakAuras.regions[data.id].region:SetStacks(1);
  1537. end
  1538.  
  1539. num = num + 1;
  1540. end
  1541.  
  1542. if (num % 50 == 0) then
  1543. frame.buttonsScroll:ResumeLayout()
  1544. frame.buttonsScroll:PerformLayout()
  1545. frame.buttonsScroll:PauseLayout()
  1546. end
  1547.  
  1548. frame.loadProgress:SetText(L["Creating buttons: "]..num.."/"..total);
  1549. frame.loadProgressNum = num;
  1550. coroutine.yield();
  1551. end
  1552.  
  1553. local co2 = coroutine.create(func2);
  1554. dynFrame:AddAction("LayoutDisplayButtons2", co2);
  1555. end
  1556.  
  1557. local co1 = coroutine.create(func1);
  1558. dynFrame:AddAction("LayoutDisplayButtons1", co1);
  1559. end
  1560.  
  1561. local function filterAnimPresetTypes(intable, id)
  1562. local ret = {};
  1563. local region = WeakAuras.regions[id] and WeakAuras.regions[id].region;
  1564. local regionType = WeakAuras.regions[id] and WeakAuras.regions[id].regionType;
  1565. local data = db.displays[id];
  1566. if(region and regionType and data) then
  1567. for key, value in pairs(intable) do
  1568. local preset = WeakAuras.anim_presets[key];
  1569. if(preset) then
  1570. if(regionType == "group" or regionType == "dynamicgroup") then
  1571. local valid = true;
  1572. for index, childId in pairs(data.controlledChildren) do
  1573. local childRegion = WeakAuras.regions[childId] and WeakAuras.regions[childId].region
  1574. if(childRegion and ((preset.use_scale and not childRegion.Scale) or (preset.use_rotate and not childRegion.Rotate))) then
  1575. valid = false;
  1576. end
  1577. end
  1578. if(valid) then
  1579. ret[key] = value;
  1580. end
  1581. else
  1582. if not((preset.use_scale and not region.Scale) or (preset.use_rotate and not region.Rotate)) then
  1583. ret[key] = value;
  1584. end
  1585. end
  1586. end
  1587. end
  1588. end
  1589. return ret;
  1590. end
  1591.  
  1592. local function removeFuncs(intable)
  1593. for i,v in pairs(intable) do
  1594. if(i == "get" or i == "set" or i == "hidden" or i == "disabled") then
  1595. intable[i] = nil;
  1596. elseif(type(v) == "table" and i ~= "values") then
  1597. removeFuncs(v);
  1598. end
  1599. end
  1600. end
  1601.  
  1602. local function getAll(data, info, ...)
  1603. local combinedValues = {};
  1604. local first = true;
  1605. for index, childId in ipairs(data.controlledChildren) do
  1606. local childData = WeakAuras.GetData(childId);
  1607. if(childData) then
  1608. WeakAuras.EnsureOptions(childId);
  1609. local childOptions = displayOptions[childId];
  1610. local childOption = childOptions;
  1611. local childOptionTable = {[0] = childOption};
  1612. for i=1,#info do
  1613. childOption = childOption.args[info[i]];
  1614. childOptionTable[i] = childOption;
  1615. end
  1616. for i=#childOptionTable,0,-1 do
  1617. if(childOptionTable[i].get) then
  1618. local values = {childOptionTable[i].get(info, ...)};
  1619. if(first) then
  1620. combinedValues = values;
  1621. first = false;
  1622. else
  1623. local same = true;
  1624. if(#combinedValues == #values) then
  1625. for j=1,#combinedValues do
  1626. if(type(combinedValues[j]) == "number" and type(values[j]) == "number") then
  1627. if((math.floor(combinedValues[j] * 100) / 100) ~= (math.floor(values[j] * 100) / 100)) then
  1628. same = false;
  1629. break;
  1630. end
  1631. else
  1632. if(combinedValues[j] ~= values[j]) then
  1633. same = false;
  1634. break;
  1635. end
  1636. end
  1637. end
  1638. else
  1639. same = false;
  1640. end
  1641. if not(same) then
  1642. return nil;
  1643. end
  1644. end
  1645. break;
  1646. end
  1647. end
  1648. end
  1649. end
  1650.  
  1651. return unpack(combinedValues);
  1652. end
  1653.  
  1654. local function setAll(data, info, ...)
  1655. for index, childId in ipairs(data.controlledChildren) do
  1656. local childData = WeakAuras.GetData(childId);
  1657. if(childData) then
  1658. WeakAuras.EnsureOptions(childId);
  1659. local childOptions = displayOptions[childId];
  1660. local childOption = childOptions;
  1661. local childOptionTable = {[0] = childOption};
  1662. for i=1,#info do
  1663. childOption = childOption.args[info[i]];
  1664. childOptionTable[i] = childOption;
  1665. end
  1666. for i=#childOptionTable,0,-1 do
  1667. if(childOptionTable[i].set) then
  1668. childOptionTable[i].set(info, ...);
  1669. break;
  1670. end
  1671. end
  1672. end
  1673. end
  1674. end
  1675.  
  1676. local function hiddenAll(data, info)
  1677. if(#data.controlledChildren == 0 and info[1] ~= "group") then
  1678. return true;
  1679. end
  1680. for index, childId in ipairs(data.controlledChildren) do
  1681. local childData = WeakAuras.GetData(childId);
  1682. if(childData) then
  1683. WeakAuras.EnsureOptions(childId);
  1684. local childOptions = displayOptions[childId];
  1685. local childOption = childOptions;
  1686. local childOptionTable = {[0] = childOption};
  1687. for i=1,#info do
  1688. childOption = childOption.args[info[i]];
  1689. childOptionTable[i] = childOption;
  1690. end
  1691. for i=#childOptionTable,0,-1 do
  1692. if(childOptionTable[i].hidden ~= nil) then
  1693. if(type(childOptionTable[i].hidden) == "boolean") then
  1694. if(childOptionTable[i].hidden) then
  1695. return true;
  1696. else
  1697. return false;
  1698. end
  1699. elseif(type(childOptionTable[i].hidden) == "function") then
  1700. if(childOptionTable[i].hidden(info)) then
  1701. return true;
  1702. end
  1703. end
  1704. end
  1705. end
  1706. end
  1707. end
  1708.  
  1709. return false;
  1710. end
  1711.  
  1712. local function disabledAll(data, info)
  1713. for index, childId in ipairs(data.controlledChildren) do
  1714. local childData = WeakAuras.GetData(childId);
  1715. if(childData) then
  1716. WeakAuras.EnsureOptions(childId);
  1717. local childOptions = displayOptions[childId];
  1718. local childOption = childOptions;
  1719. local childOptionTable = {[0] = childOption};
  1720. for i=1,#info do
  1721. childOption = childOption.args[info[i]];
  1722. childOptionTable[i] = childOption;
  1723. end
  1724. for i=#childOptionTable,0,-1 do
  1725. if(childOptionTable[i].disabled ~= nil) then
  1726. if(type(childOptionTable[i].disabled) == "boolean") then
  1727. if(childOptionTable[i].disabled) then
  1728. return true;
  1729. else
  1730. return false;
  1731. end
  1732. elseif(type(childOptionTable[i].disabled) == "function") then
  1733. if(childOptionTable[i].disabled(info)) then
  1734. return true;
  1735. end
  1736. end
  1737. end
  1738. end
  1739. end
  1740. end
  1741.  
  1742. return false;
  1743. end
  1744.  
  1745. local function replaceNameDescFuncs(intable, data)
  1746. local function sameAll(info)
  1747. local combinedValues = {};
  1748. local first = true;
  1749. for index, childId in ipairs(data.controlledChildren) do
  1750. local childData = WeakAuras.GetData(childId);
  1751. if(childData) then
  1752. WeakAuras.EnsureOptions(childId);
  1753. local childOptions = displayOptions[childId];
  1754. local childOption = childOptions;
  1755. local childOptionTable = {[0] = childOption};
  1756. for i=1,#info do
  1757. childOption = childOption.args[info[i]];
  1758. childOptionTable[i] = childOption;
  1759. end
  1760. for i=#childOptionTable,0,-1 do
  1761. if(childOptionTable[i].get) then
  1762. local values = {childOptionTable[i].get(info)};
  1763. if(first) then
  1764. combinedValues = values;
  1765. first = false;
  1766. else
  1767. local same = true;
  1768. if(#combinedValues == #values) then
  1769. for j=1,#combinedValues do
  1770. if(type(combinedValues[j]) == "number" and type(values[j]) == "number") then
  1771. if((math.floor(combinedValues[j] * 100) / 100) ~= (math.floor(values[j] * 100) / 100)) then
  1772. same = false;
  1773. break;
  1774. end
  1775. else
  1776. if(combinedValues[j] ~= values[j]) then
  1777. same = false;
  1778. break;
  1779. end
  1780. end
  1781. end
  1782. else
  1783. same = false;
  1784. end
  1785. if not(same) then
  1786. return nil;
  1787. end
  1788. end
  1789. break;
  1790. end
  1791. end
  1792. end
  1793. end
  1794.  
  1795. return true;
  1796. end
  1797.  
  1798. local function nameAll(info)
  1799. local combinedName;
  1800. local first = true;
  1801. for index, childId in ipairs(data.controlledChildren) do
  1802. local childData = WeakAuras.GetData(childId);
  1803. if(childData) then
  1804. WeakAuras.EnsureOptions(childId);
  1805. local childOption = displayOptions[childId];
  1806. if not(childOption) then
  1807. return "error 1";
  1808. end
  1809. for i=1,#info do
  1810. childOption = childOption.args[info[i]];
  1811. if not(childOption) then
  1812. return "error 2 - "..childId.." - "..table.concat(info, ", ").." - "..i;
  1813. end
  1814. end
  1815. local name;
  1816. if(type(childOption.name) == "function") then
  1817. name = childOption.name(info);
  1818. else
  1819. name = childOption.name;
  1820. end
  1821. if(first) then
  1822. combinedName = name;
  1823. first = false;
  1824. elseif not(combinedName == name) then
  1825. return childOption.name("default");
  1826. end
  1827. end
  1828. end
  1829.  
  1830. return combinedName;
  1831. end
  1832.  
  1833. local function descAll(info)
  1834. local combinedDesc;
  1835. local first = true;
  1836. for index, childId in ipairs(data.controlledChildren) do
  1837. local childData = WeakAuras.GetData(childId);
  1838. if(childData) then
  1839. WeakAuras.EnsureOptions(childId);
  1840. local childOption = displayOptions[childId];
  1841. if not(childOption) then
  1842. return "error"
  1843. end
  1844. for i=1,#info do
  1845. childOption = childOption.args[info[i]];
  1846. if not(childOption) then
  1847. return "error"
  1848. end
  1849. end
  1850. local desc;
  1851. if(type(childOption.desc) == "function") then
  1852. desc = childOption.desc(info);
  1853. else
  1854. desc = childOption.desc;
  1855. end
  1856. if(first) then
  1857. combinedDesc = desc;
  1858. first = false;
  1859. elseif not(combinedDesc == desc) then
  1860. return L["Not all children have the same value for this option"];
  1861. end
  1862. end
  1863. end
  1864.  
  1865. return combinedDesc;
  1866. end
  1867.  
  1868. local function recurse(intable)
  1869. for i,v in pairs(intable) do
  1870. if(i == "name" and type(v) ~= "table") then
  1871. intable.name = function(info)
  1872. local name = nameAll(info);
  1873. if(sameAll(info)) then
  1874. return name;
  1875. else
  1876. if(name == "") then
  1877. return name;
  1878. else
  1879. return "|cFF4080FF"..(name or "error");
  1880. end
  1881. end
  1882. end
  1883. intable.desc = function(info)
  1884. if(sameAll(info)) then
  1885. return descAll(info);
  1886. else
  1887. local values = {};
  1888. for index, childId in ipairs(data.controlledChildren) do
  1889. local childData = WeakAuras.GetData(childId);
  1890. if(childData) then
  1891. WeakAuras.EnsureOptions(childId);
  1892. local childOptions = displayOptions[childId];
  1893. local childOption = childOptions;
  1894. local childOptionTable = {[0] = childOption};
  1895. for i=1,#info do
  1896. childOption = childOption.args[info[i]];
  1897. childOptionTable[i] = childOption;
  1898. end
  1899. for i=#childOptionTable,0,-1 do
  1900. if(childOptionTable[i].get) then
  1901. if(intable.type == "toggle") then
  1902. local name, tri;
  1903. if(type(childOption.name) == "function") then
  1904. name = childOption.name(info);
  1905. tri = true;
  1906. else
  1907. name = childOption.name;
  1908. end
  1909. if(tri and childOptionTable[i].get(info)) then
  1910. tinsert(values, "|cFFE0E000"..childId..": |r"..name);
  1911. elseif(tri) then
  1912. tinsert(values, "|cFFE0E000"..childId..": |r"..L["Ignored"]);
  1913. elseif(childOptionTable[i].get(info)) then
  1914. tinsert(values, "|cFFE0E000"..childId..": |r|cFF00FF00"..L["Enabled"]);
  1915. else
  1916. tinsert(values, "|cFFE0E000"..childId..": |r|cFFFF0000"..L["Disabled"]);
  1917. end
  1918. elseif(intable.type == "color") then
  1919. local r, g, b = childOptionTable[i].get(info);
  1920. r, g, b = r or 1, g or 1, b or 1;
  1921. tinsert(values, ("|cFF%2x%2x%2x%s"):format(r * 220 + 35, g * 220 + 35, b * 220 + 35, childId));
  1922. elseif(intable.type == "select") then
  1923. local selectValues = type(intable.values) == "table" and intable.values or intable.values();
  1924. local key = childOptionTable[i].get(info);
  1925. local display = key and selectValues[key] or L["None"];
  1926. tinsert(values, "|cFFE0E000"..childId..": |r"..display);
  1927. else
  1928. local display = childOptionTable[i].get(info) or L["None"];
  1929. if(type(display) == "number") then
  1930. display = math.floor(display * 100) / 100;
  1931. end
  1932. tinsert(values, "|cFFE0E000"..childId..": |r"..display);
  1933. end
  1934. break;
  1935. end
  1936. end
  1937. end
  1938. end
  1939. return table.concat(values, "\n");
  1940. end
  1941. end
  1942. elseif(type(v) == "table" and i ~= "values") then
  1943. recurse(v);
  1944. end
  1945. end
  1946. end
  1947. recurse(intable);
  1948. end
  1949.  
  1950. local function replaceImageFuncs(intable, data)
  1951. local function imageAll(info)
  1952. local combinedImage = {};
  1953. local first = true;
  1954. for index, childId in ipairs(data.controlledChildren) do
  1955. local childData = WeakAuras.GetData(childId);
  1956. if(childData) then
  1957. WeakAuras.EnsureOptions(childId);
  1958. local childOption = displayOptions[childId];
  1959. if not(childOption) then
  1960. return "error"
  1961. end
  1962. for i=1,#info do
  1963. childOption = childOption.args[info[i]];
  1964. if not(childOption) then
  1965. return "error"
  1966. end
  1967. end
  1968. local image;
  1969. if not(childOption.image) then
  1970. return "", 0, 0;
  1971. else
  1972. image = {childOption.image(info)};
  1973. end
  1974. if(first) then
  1975. combinedImage = image;
  1976. first = false;
  1977. else
  1978. if not(combinedImage[1] == image[1]) then
  1979. return "", 0, 0;
  1980. end
  1981. end
  1982. end
  1983. end
  1984.  
  1985. return unpack(combinedImage);
  1986. end
  1987.  
  1988. local function recurse(intable)
  1989. for i,v in pairs(intable) do
  1990. if(i == "image" and type(v) == "function") then
  1991. intable[i] = imageAll;
  1992. elseif(type(v) == "table" and i ~= "values") then
  1993. recurse(v);
  1994. end
  1995. end
  1996. end
  1997. recurse(intable);
  1998. end
  1999.  
  2000. function WeakAuras.AddOption(id, data)
  2001. local regionOption;
  2002. if(regionOptions[data.regionType]) then
  2003. regionOption = regionOptions[data.regionType].create(id, data);
  2004. else
  2005. regionOption = {
  2006. unsupported = {
  2007. type = "description",
  2008. name = L["This region of type \"%s\" has no configuration options."]:format(data.regionType)
  2009. }
  2010. };
  2011. end
  2012.  
  2013. displayOptions[id] = {
  2014. type = "group",
  2015. childGroups = "tab",
  2016. args = {
  2017. region = {
  2018. type = "group",
  2019. name = L["Display"],
  2020. order = 10,
  2021. get = function(info)
  2022. if(info.type == "color") then
  2023. data[info[#info]] = data[info[#info]] or {};
  2024. local c = data[info[#info]];
  2025. return c[1], c[2], c[3], c[4];
  2026. else
  2027. return data[info[#info]];
  2028. end
  2029. end,
  2030. set = function(info, v, g, b, a)
  2031. if(info.type == "color") then
  2032. data[info[#info]] = data[info[#info]] or {};
  2033. local c = data[info[#info]];
  2034. c[1], c[2], c[3], c[4] = v, g, b, a;
  2035. elseif(info.type == "toggle") then
  2036. data[info[#info]] = v;
  2037. else
  2038. data[info[#info]] = (v ~= "" and v) or nil;
  2039. end
  2040. WeakAuras.Add(data);
  2041. WeakAuras.SetThumbnail(data);
  2042. WeakAuras.SetIconNames(data);
  2043. if(data.parent) then
  2044. local parentData = WeakAuras.GetData(data.parent);
  2045. if(parentData) then
  2046. WeakAuras.Add(parentData);
  2047. WeakAuras.SetThumbnail(parentData);
  2048. end
  2049. end
  2050. WeakAuras.ResetMoverSizer();
  2051. end,
  2052. args = regionOption
  2053. },
  2054. trigger = {
  2055. type = "group",
  2056. name = L["Trigger"],
  2057. order = 20,
  2058. args = {}
  2059. },
  2060. load = {
  2061. type = "group",
  2062. name = L["Load"],
  2063. order = 30,
  2064. get = function(info) return data.load[info[#info]] end,
  2065. set = function(info, v)
  2066. data.load[info[#info]] = (v ~= "" and v) or nil;
  2067. WeakAuras.Add(data);
  2068. WeakAuras.SetThumbnail(data);
  2069. WeakAuras.ScanForLoads();
  2070. WeakAuras.SortDisplayButtons();
  2071. end,
  2072. args = {}
  2073. },
  2074. action = {
  2075. type = "group",
  2076. name = L["Actions"],
  2077. order = 50,
  2078. get = function(info)
  2079. local split = info[#info]:find("_");
  2080. if(split) then
  2081. local field, value = info[#info]:sub(1, split-1), info[#info]:sub(split+1);
  2082. if(data.actions and data.actions[field]) then
  2083. return data.actions[field][value];
  2084. else
  2085. return nil;
  2086. end
  2087. end
  2088. end,
  2089. set = function(info, v)
  2090. local split = info[#info]:find("_");
  2091. local field, value = info[#info]:sub(1, split-1), info[#info]:sub(split+1);
  2092. data.actions = data.actions or {};
  2093. data.actions[field] = data.actions[field] or {};
  2094. data.actions[field][value] = v;
  2095. if(value == "sound" or value == "sound_path") then
  2096. PlaySoundFile(v, data.actions.start.sound_channel);
  2097. end
  2098. WeakAuras.Add(data);
  2099. end,
  2100. args = {
  2101. start_header = {
  2102. type = "header",
  2103. name = L["On Show"],
  2104. order = 0.5
  2105. },
  2106. start_do_message = {
  2107. type = "toggle",
  2108. name = L["Chat Message"],
  2109. order = 1
  2110. },
  2111. start_message_type = {
  2112. type = "select",
  2113. name = L["Message Type"],
  2114. order = 2,
  2115. values = send_chat_message_types,
  2116. disabled = function() return not data.actions.start.do_message end
  2117. },
  2118. start_message_space = {
  2119. type = "execute",
  2120. name = "",
  2121. order = 3,
  2122. image = function() return "", 0, 0 end,
  2123. hidden = function() return not(data.actions.start.message_type == "WHISPER" or data.actions.start.message_type == "CHANNEL" or data.actions.start.message_type == "COMBAT" or data.actions.start.message_type == "PRINT") end
  2124. },
  2125. start_message_color = {
  2126. type = "color",
  2127. name = L["Color"],
  2128. order = 3,
  2129. hasAlpha = false,
  2130. hidden = function() return not(data.actions.start.message_type == "COMBAT" or data.actions.start.message_type == "PRINT") end,
  2131. get = function() return data.actions.start.r or 1, data.actions.start.g or 1, data.actions.start.b or 1 end,
  2132. set = function(info, r, g, b)
  2133. data.actions.start.r = r;
  2134. data.actions.start.g = g;
  2135. data.actions.start.b = b;
  2136. WeakAuras.Add(data);
  2137. end
  2138. },
  2139. start_message_dest = {
  2140. type = "input",
  2141. name = L["Send To"],
  2142. order = 4,
  2143. disabled = function() return not data.actions.start.do_message end,
  2144. hidden = function() return data.actions.start.message_type ~= "WHISPER" end
  2145. },
  2146. start_message_channel = {
  2147. type = "input",
  2148. name = L["Channel Number"],
  2149. order = 4,
  2150. disabled = function() return not data.actions.start.do_message end,
  2151. hidden = function() return data.actions.start.message_type ~= "CHANNEL" end
  2152. },
  2153. start_message = {
  2154. type = "input",
  2155. name = L["Message"],
  2156. width = "double",
  2157. order = 5,
  2158. disabled = function() return not data.actions.start.do_message end
  2159. },
  2160. start_do_sound = {
  2161. type = "toggle",
  2162. width = "double",
  2163. name = L["Play Sound"],
  2164. order = 7
  2165. },
  2166. start_sound = {
  2167. type = "select",
  2168. name = L["Sound"],
  2169. order = 8,
  2170. values = sound_types,
  2171. disabled = function() return not data.actions.start.do_sound end
  2172. },
  2173. start_sound_channel = {
  2174. type = "select",
  2175. name = L["Sound Channel"],
  2176. order = 8.5,
  2177. values = WeakAuras.sound_channel_types,
  2178. disabled = function() return not data.actions.start.do_sound end,
  2179. get = function() return data.actions.start.sound_channel or "SFX" end
  2180. },
  2181. start_sound_path = {
  2182. type = "input",
  2183. name = L["Sound File Path"],
  2184. order = 9,
  2185. width = "double",
  2186. hidden = function() return data.actions.start.sound ~= " custom" end,
  2187. disabled = function() return not data.actions.start.do_sound end
  2188. },
  2189. start_do_glow = {
  2190. type = "toggle",
  2191. name = L["Button Glow"],
  2192. order = 10.1
  2193. },
  2194. start_glow_action = {
  2195. type = "select",
  2196. name = L["Glow Action"],
  2197. order = 10.2,
  2198. values = WeakAuras.glow_action_types,
  2199. disabled = function() return not data.actions.start.do_glow end
  2200. },
  2201. start_glow_frame = {
  2202. type = "input",
  2203. name = L["Frame"],
  2204. order = 10.3,
  2205. hidden = function() return not data.actions.start.do_glow end
  2206. },
  2207. start_choose_glow_frame = {
  2208. type = "execute",
  2209. name = L["Choose"],
  2210. order = 10.4,
  2211. hidden = function() return not data.actions.start.do_glow end,
  2212. func = function()
  2213. if(data.controlledChildren and data.controlledChildren[1]) then
  2214. WeakAuras.PickDisplay(data.controlledChildren[1]);
  2215. WeakAuras.StartFrameChooser(WeakAuras.GetData(data.controlledChildren[1]), {"actions", "start", "glow_frame"});
  2216. else
  2217. WeakAuras.StartFrameChooser(data, {"actions", "start", "glow_frame"});
  2218. end
  2219. end
  2220. },
  2221. start_do_custom = {
  2222. type = "toggle",
  2223. name = L["Custom"],
  2224. order = 11,
  2225. width = "double"
  2226. },
  2227. start_custom = {
  2228. type = "input",
  2229. width = "normal",
  2230. name = L["Custom Code"],
  2231. order = 13,
  2232. multiline = true,
  2233. hidden = function() return not data.actions.start.do_custom end
  2234. },
  2235. start_expand = {
  2236. type = "execute",
  2237. order = 14,
  2238. name = L["Expand Text Editor"],
  2239. func = function()
  2240. WeakAuras.TextEditor(data, {"actions", "start", "custom"}, true)
  2241. end,
  2242. hidden = function() return not data.actions.start.do_custom end
  2243. },
  2244. start_customError = {
  2245. type = "description",
  2246. name = function()
  2247. if not(data.actions.start.custom) then
  2248. return "";
  2249. end
  2250. local _, errorString = loadstring("return function() "..data.actions.start.custom.." end");
  2251. return errorString and "|cFFFF0000"..errorString or "";
  2252. end,
  2253. width = "double",
  2254. order = 15,
  2255. hidden = function()
  2256. if not(data.actions.start.do_custom and data.actions.start.custom) then
  2257. return true;
  2258. else
  2259. local loadedFunction, errorString = loadstring("return function() "..data.actions.start.custom.." end");
  2260. if(errorString and not loadedFunction) then
  2261. return false;
  2262. else
  2263. return true;
  2264. end
  2265. end
  2266. end
  2267. },
  2268. finish_header = {
  2269. type = "header",
  2270. name = L["On Hide"],
  2271. order = 20.5
  2272. },
  2273. finish_do_message = {
  2274. type = "toggle",
  2275. name = L["Chat Message"],
  2276. order = 21
  2277. },
  2278. finish_message_type = {
  2279. type = "select",
  2280. name = L["Message Type"],
  2281. order = 22,
  2282. values = send_chat_message_types,
  2283. disabled = function() return not data.actions.finish.do_message end
  2284. },
  2285. finish_message_space = {
  2286. type = "execute",
  2287. name = "",
  2288. order = 23,
  2289. image = function() return "", 0, 0 end,
  2290. hidden = function() return not(data.actions.finish.message_type == "WHISPER" or data.actions.finish.message_type == "CHANNEL") end
  2291. },
  2292. finish_message_color = {
  2293. type = "color",
  2294. name = L["Color"],
  2295. order = 23,
  2296. hasAlpha = false,
  2297. hidden = function() return not(data.actions.finish.message_type == "COMBAT" or data.actions.finish.message_type == "PRINT") end,
  2298. get = function() return data.actions.finish.r or 1, data.actions.finish.g or 1, data.actions.finish.b or 1 end,
  2299. set = function(info, r, g, b)
  2300. data.actions.finish.r = r;
  2301. data.actions.finish.g = g;
  2302. data.actions.finish.b = b;
  2303. WeakAuras.Add(data);
  2304. end
  2305. },
  2306. finish_message_dest = {
  2307. type = "input",
  2308. name = L["Send To"],
  2309. order = 24,
  2310. disabled = function() return not data.actions.finish.do_message end,
  2311. hidden = function() return data.actions.finish.message_type ~= "WHISPER" end
  2312. },
  2313. finish_message_channel = {
  2314. type = "input",
  2315. name = L["Channel Number"],
  2316. order = 24,
  2317. disabled = function() return not data.actions.finish.do_message end,
  2318. hidden = function() return data.actions.finish.message_type ~= "CHANNEL" end
  2319. },
  2320. finish_message = {
  2321. type = "input",
  2322. name = L["Message"],
  2323. width = "double",
  2324. order = 25,
  2325. disabled = function() return not data.actions.finish.do_message end
  2326. },
  2327. finish_do_sound = {
  2328. type = "toggle",
  2329. width = "double",
  2330. name = L["Play Sound"],
  2331. order = 27
  2332. },
  2333. finish_sound = {
  2334. type = "select",
  2335. name = L["Sound"],
  2336. order = 28,
  2337. values = sound_types,
  2338. disabled = function() return not data.actions.finish.do_sound end
  2339. },
  2340. finish_sound_channel = {
  2341. type = "select",
  2342. name = L["Sound Channel"],
  2343. order = 28.5,
  2344. values = WeakAuras.sound_channel_types,
  2345. disabled = function() return not data.actions.finish.do_sound end,
  2346. get = function() return data.actions.finish.sound_channel or "Master" end
  2347. },
  2348. finish_sound_path = {
  2349. type = "input",
  2350. name = L["Sound File Path"],
  2351. order = 29,
  2352. width = "double",
  2353. hidden = function() return data.actions.finish.sound ~= " custom" end,
  2354. disabled = function() return not data.actions.finish.do_sound end
  2355. },
  2356. finish_do_glow = {
  2357. type = "toggle",
  2358. name = L["Button Glow"],
  2359. order = 30.1
  2360. },
  2361. finish_glow_action = {
  2362. type = "select",
  2363. name = L["Glow Action"],
  2364. order = 30.2,
  2365. values = WeakAuras.glow_action_types,
  2366. disabled = function() return not data.actions.finish.do_glow end
  2367. },
  2368. finish_glow_frame = {
  2369. type = "input",
  2370. name = L["Frame"],
  2371. order = 30.3,
  2372. hidden = function() return not data.actions.finish.do_glow end
  2373. },
  2374. finish_choose_glow_frame = {
  2375. type = "execute",
  2376. name = L["Choose"],
  2377. order = 30.4,
  2378. hidden = function() return not data.actions.finish.do_glow end,
  2379. func = function()
  2380. if(data.controlledChildren and data.controlledChildren[1]) then
  2381. WeakAuras.PickDisplay(data.controlledChildren[1]);
  2382. WeakAuras.StartFrameChooser(WeakAuras.GetData(data.controlledChildren[1]), {"actions", "finish", "glow_frame"});
  2383. else
  2384. WeakAuras.StartFrameChooser(data, {"actions", "finish", "glow_frame"});
  2385. end
  2386. end
  2387. },
  2388. finish_do_custom = {
  2389. type = "toggle",
  2390. name = L["Custom"],
  2391. order = 31,
  2392. width = "double"
  2393. },
  2394. finish_custom = {
  2395. type = "input",
  2396. width = "half",
  2397. name = L["Custom Code"],
  2398. order = 33,
  2399. multiline = true,
  2400. width = "normal",
  2401. hidden = function() return not data.actions.finish.do_custom end
  2402. },
  2403. finish_expand = {
  2404. type = "execute",
  2405. order = 34,
  2406. name = L["Expand Text Editor"],
  2407. func = function()
  2408. WeakAuras.TextEditor(data, {"actions", "finish", "custom"}, true)
  2409. end,
  2410. hidden = function() return not data.actions.finish.do_custom end
  2411. },
  2412. finish_customError = {
  2413. type = "description",
  2414. name = function()
  2415. if not(data.actions.finish.custom) then
  2416. return "";
  2417. end
  2418. local _, errorString = loadstring("return function() "..data.actions.finish.custom.." end");
  2419. return errorString and "|cFFFF0000"..errorString or "";
  2420. end,
  2421. width = "double",
  2422. order = 35,
  2423. hidden = function()
  2424. if not(data.actions.finish.do_custom and data.actions.finish.custom) then
  2425. return true;
  2426. else
  2427. local loadedFunction, errorString = loadstring("return function() "..data.actions.finish.custom.." end");
  2428. if(errorString and not loadedFunction) then
  2429. return false;
  2430. else
  2431. return true;
  2432. end
  2433. end
  2434. end
  2435. }
  2436. }
  2437. },
  2438. animation = {
  2439. type = "group",
  2440. name = L["Animations"],
  2441. order = 60,
  2442. get = function(info)
  2443. local split = info[#info]:find("_");
  2444. if(split) then
  2445. local field, value = info[#info]:sub(1, split-1), info[#info]:sub(split+1);
  2446.  
  2447. if(data.animation and data.animation[field]) then
  2448. return data.animation[field][value];
  2449. else
  2450. if(value == "scalex" or value == "scaley") then
  2451. return 1;
  2452. else
  2453. return nil;
  2454. end
  2455. end
  2456. end
  2457. end,
  2458. set = function(info, v)
  2459. local split = info[#info]:find("_");
  2460. local field, value = info[#info]:sub(1, split-1), info[#info]:sub(split+1);
  2461. data.animation = data.animation or {};
  2462. data.animation[field] = data.animation[field] or {};
  2463. data.animation[field][value] = v;
  2464. if(field == "main" and not WeakAuras.IsAnimating("display", id)) then
  2465. WeakAuras.Animate("display", id, "main", data.animation.main, WeakAuras.regions[id].region, false, nil, true);
  2466. if(WeakAuras.clones[id]) then
  2467. for cloneId, cloneRegion in pairs(WeakAuras.clones[id]) do
  2468. WeakAuras.Animate("display", id, "main", data.animation.main, cloneRegion, false, nil, true, cloneId);
  2469. end
  2470. end
  2471. end
  2472. WeakAuras.Add(data);
  2473. end,
  2474. disabled = function(info, v)
  2475. local split = info[#info]:find("_");
  2476. local valueToType = {
  2477. alphaType = "use_alpha",
  2478. alpha = "use_alpha",
  2479. translateType = "use_translate",
  2480. x = "use_translate",
  2481. y = "use_translate",
  2482. scaleType = "use_scale",
  2483. scalex = "use_scale",
  2484. scaley = "use_scale",
  2485. rotateType = "use_rotate",
  2486. rotate = "use_rotate",
  2487. colorType = "use_color",
  2488. color = "use_color"
  2489. }
  2490. if(split) then
  2491. local field, value = info[#info]:sub(1, split-1), info[#info]:sub(split+1);
  2492. if(data.animation and data.animation[field]) then
  2493. if(valueToType[value]) then
  2494. return not data.animation[field][valueToType[value]];
  2495. else
  2496. return false;
  2497. end
  2498. else
  2499. return true;
  2500. end
  2501. else
  2502. return false;
  2503. end
  2504. end,
  2505. args = {
  2506. start_header = {
  2507. type = "header",
  2508. name = L["Start"],
  2509. order = 30
  2510. },
  2511. start_type = {
  2512. type = "select",
  2513. name = L["Type"],
  2514. order = 32,
  2515. values = anim_types,
  2516. disabled = false
  2517. },
  2518. start_preset = {
  2519. type = "select",
  2520. name = L["Preset"],
  2521. order = 33,
  2522. values = function() return filterAnimPresetTypes(anim_start_preset_types, id) end,
  2523. hidden = function() return data.animation.start.type ~= "preset" end
  2524. },
  2525. start_duration_type_no_choice = {
  2526. type = "select",
  2527. name = L["Time in"],
  2528. order = 33,
  2529. width = "half",
  2530. values = duration_types_no_choice,
  2531. disabled = true,
  2532. hidden = function() return data.animation.start.type ~= "custom" or WeakAuras.CanHaveDuration(data) end,
  2533. get = function() return "seconds" end
  2534. },
  2535. start_duration_type = {
  2536. type = "select",
  2537. name = L["Time in"],
  2538. order = 33,
  2539. width = "half",
  2540. values = duration_types,
  2541. hidden = function() return data.animation.start.type ~= "custom" or not WeakAuras.CanHaveDuration(data) end
  2542. },
  2543. start_duration = {
  2544. type = "input",
  2545. name = function()
  2546. if(data.animation.start.duration_type == "relative") then
  2547. return L["% of Progress"];
  2548. else
  2549. return L["Duration (s)"];
  2550. end
  2551. end,
  2552. desc = function()
  2553. if(data.animation.start.duration_type == "relative") then
  2554. return L["Animation relative duration description"];
  2555. else
  2556. return L["The duration of the animation in seconds."];
  2557. end
  2558. end,
  2559. order = 33.5,
  2560. width = "half",
  2561. hidden = function() return data.animation.start.type ~= "custom" end
  2562. },
  2563. start_use_alpha = {
  2564. type = "toggle",
  2565. name = L["Fade In"],
  2566. order = 34,
  2567. hidden = function() return data.animation.start.type ~= "custom" end
  2568. },
  2569. start_alphaType = {
  2570. type = "select",
  2571. name = L["Type"],
  2572. order = 35,
  2573. values = anim_alpha_types,
  2574. hidden = function() return data.animation.start.type ~= "custom" end
  2575. },
  2576. start_alphaFunc = {
  2577. type = "input",
  2578. width = "normal",
  2579. multiline = true,
  2580. name = L["Custom Function"],
  2581. order = 35.3,
  2582. hidden = function() return data.animation.start.type ~= "custom" or data.animation.start.alphaType ~= "custom" or not data.animation.start.use_alpha end,
  2583. get = function() return data.animation.start.alphaFunc and data.animation.start.alphaFunc:sub(8); end,
  2584. set = function(info, v) data.animation.start.alphaFunc = "return "..(v or ""); WeakAuras.Add(data); end
  2585. },
  2586. start_alphaFunc_expand = {
  2587. type = "execute",
  2588. order = 35.4,
  2589. name = L["Expand Text Editor"],
  2590. func = function()
  2591. WeakAuras.TextEditor(data, {"animation", "start", "alphaFunc"}, nil, true)
  2592. end,
  2593. hidden = function() return data.animation.start.type ~= "custom" or data.animation.start.alphaType ~= "custom" or not data.animation.start.use_alpha end
  2594. },
  2595. start_alphaFuncError = {
  2596. type = "description",
  2597. name = function()
  2598. if not(data.animation.start.alphaFunc) then
  2599. return "";
  2600. end
  2601. local _, errorString = loadstring(data.animation.start.alphaFunc or "");
  2602. return errorString and "|cFFFF0000"..errorString or "";
  2603. end,
  2604. width = "double",
  2605. order = 35.6,
  2606. hidden = function()
  2607. if(data.animation.start.type ~= "custom" or data.animation.start.alphaType ~= "custom" or not data.animation.start.use_alpha) then
  2608. return true;
  2609. else
  2610. local loadedFunction, errorString = loadstring(data.animation.start.alphaFunc or "");
  2611. if(errorString and not loadedFunction) then
  2612. return false;
  2613. else
  2614. return true;
  2615. end
  2616. end
  2617. end
  2618. },
  2619. start_alpha = {
  2620. type = "range",
  2621. name = L["Alpha"],
  2622. width = "double",
  2623. order = 36,
  2624. min = 0,
  2625. max = 1,
  2626. bigStep = 0.01,
  2627. isPercent = true,
  2628. hidden = function() return data.animation.start.type ~= "custom" end
  2629. },
  2630. start_use_translate = {
  2631. type = "toggle",
  2632. name = L["Slide In"],
  2633. order = 38,
  2634. hidden = function() return data.animation.start.type ~= "custom" end
  2635. },
  2636. start_translateType = {
  2637. type = "select",
  2638. name = L["Type"],
  2639. order = 39,
  2640. values = anim_translate_types,
  2641. hidden = function() return data.animation.start.type ~= "custom" end
  2642. },
  2643. start_translateFunc = {
  2644. type = "input",
  2645. multiline = true,
  2646. name = L["Custom Function"],
  2647. width = "normal",
  2648. order = 39.3,
  2649. hidden = function() return data.animation.start.type ~= "custom" or data.animation.start.translateType ~= "custom" or not data.animation.start.use_translate end,
  2650. get = function() return data.animation.start.translateFunc and data.animation.start.translateFunc:sub(8); end,
  2651. set = function(info, v) data.animation.start.translateFunc = "return "..(v or ""); WeakAuras.Add(data); end
  2652. },
  2653. start_translateFunc_expand = {
  2654. type = "execute",
  2655. order = 39.4,
  2656. name = L["Expand Text Editor"],
  2657. func = function()
  2658. WeakAuras.TextEditor(data, {"animation", "start", "translateFunc"}, nil, true)
  2659. end,
  2660. hidden = function() return data.animation.start.type ~= "custom" or data.animation.start.translateType ~= "custom" or not data.animation.start.use_translate end,
  2661. },
  2662. start_translateFuncError = {
  2663. type = "description",
  2664. name = function()
  2665. if not(data.animation.start.translateFunc) then
  2666. return "";
  2667. end
  2668. local _, errorString = loadstring(data.animation.start.translateFunc or "");
  2669. return errorString and "|cFFFF0000"..errorString or "";
  2670. end,
  2671. width = "double",
  2672. order = 39.6,
  2673. hidden = function()
  2674. if(data.animation.start.type ~= "custom" or data.animation.start.translateType ~= "custom" or not data.animation.start.use_translate) then
  2675. return true;
  2676. else
  2677. local loadedFunction, errorString = loadstring(data.animation.start.translateFunc or "");
  2678. if(errorString and not loadedFunction) then
  2679. return false;
  2680. else
  2681. return true;
  2682. end
  2683. end
  2684. end
  2685. },
  2686. start_x = {
  2687. type = "range",
  2688. name = L["X Offset"],
  2689. order = 40,
  2690. softMin = -200,
  2691. softMax = 200,
  2692. step = 1,
  2693. bigStep = 5,
  2694. hidden = function() return data.animation.start.type ~= "custom" end
  2695. },
  2696. start_y = {
  2697. type = "range",
  2698. name = L["Y Offset"],
  2699. order = 41,
  2700. softMin = -200,
  2701. softMax = 200,
  2702. step = 1,
  2703. bigStep = 5,
  2704. hidden = function() return data.animation.start.type ~= "custom" end
  2705. },
  2706. start_use_scale = {
  2707. type = "toggle",
  2708. name = L["Zoom In"],
  2709. order = 42,
  2710. hidden = function()
  2711. return (
  2712. data.animation.start.type ~= "custom"
  2713. or not WeakAuras.regions[id].region.Scale
  2714. ) end
  2715. },
  2716. start_scaleType = {
  2717. type = "select",
  2718. name = L["Type"],
  2719. order = 43,
  2720. values = anim_scale_types,
  2721. hidden = function() return (data.animation.start.type ~= "custom" or not WeakAuras.regions[id].region.Scale) end
  2722. },
  2723. start_scaleFunc = {
  2724. type = "input",
  2725. multiline = true,
  2726. name = L["Custom Function"],
  2727. width = "normal",
  2728. order = 43.3,
  2729. hidden = function() return data.animation.start.type ~= "custom" or data.animation.start.scaleType ~= "custom" or not (data.animation.start.use_scale and WeakAuras.regions[id].region.Scale) end,
  2730. get = function() return data.animation.start.scaleFunc and data.animation.start.scaleFunc:sub(8); end,
  2731. set = function(info, v) data.animation.start.scaleFunc = "return "..(v or ""); WeakAuras.Add(data); end
  2732. },
  2733. start_scaleFunc_expand = {
  2734. type = "execute",
  2735. order = 43.4,
  2736. name = L["Expand Text Editor"],
  2737. func = function()
  2738. WeakAuras.TextEditor(data, {"animation", "start", "scaleFunc"}, nil, true)
  2739. end,
  2740. hidden = function() return data.animation.start.type ~= "custom" or data.animation.start.scaleType ~= "custom" or not (data.animation.start.use_scale and WeakAuras.regions[id].region.Scale) end,
  2741. },
  2742. start_scaleFuncError = {
  2743. type = "description",
  2744. name = function()
  2745. if not(data.animation.start.scaleFunc) then
  2746. return "";
  2747. end
  2748. local _, errorString = loadstring(data.animation.start.scaleFunc or "");
  2749. return errorString and "|cFFFF0000"..errorString or "";
  2750. end,
  2751. width = "double",
  2752. order = 43.6,
  2753. hidden = function()
  2754. if(data.animation.start.type ~= "custom" or data.animation.start.scaleType ~= "custom" or not (data.animation.start.use_scale and WeakAuras.regions[id].region.Scale)) then
  2755. return true;
  2756. else
  2757. local loadedFunction, errorString = loadstring(data.animation.start.scaleFunc or "");
  2758. if(errorString and not loadedFunction) then
  2759. return false;
  2760. else
  2761. return true;
  2762. end
  2763. end
  2764. end
  2765. },
  2766. start_scalex = {
  2767. type = "range",
  2768. name = L["X Scale"],
  2769. order = 44,
  2770. softMin = 0,
  2771. softMax = 5,
  2772. step = 0.01,
  2773. bigStep = 0.1,
  2774. hidden = function() return (data.animation.start.type ~= "custom" or not WeakAuras.regions[id].region.Scale) end
  2775. },
  2776. start_scaley = {
  2777. type = "range",
  2778. name = L["Y Scale"],
  2779. order = 45,
  2780. softMin = 0,
  2781. softMax = 5,
  2782. step = 0.01,
  2783. bigStep = 0.1,
  2784. hidden = function() return (data.animation.start.type ~= "custom" or not WeakAuras.regions[id].region.Scale) end
  2785. },
  2786. start_use_rotate = {
  2787. type = "toggle",
  2788. name = L["Rotate In"],
  2789. order = 46,
  2790. hidden = function() return (data.animation.start.type ~= "custom" or not WeakAuras.regions[id].region.Rotate) end
  2791. },
  2792. start_rotateType = {
  2793. type = "select",
  2794. name = L["Type"],
  2795. order = 47,
  2796. values = anim_rotate_types,
  2797. hidden = function() return (data.animation.start.type ~= "custom" or not WeakAuras.regions[id].region.Rotate) end
  2798. },
  2799. start_rotateFunc = {
  2800. type = "input",
  2801. multiline = true,
  2802. name = L["Custom Function"],
  2803. width = "normal",
  2804. order = 47.3,
  2805. hidden = function() return data.animation.start.type ~= "custom" or data.animation.start.rotateType ~= "custom" or not (data.animation.start.use_rotate and WeakAuras.regions[id].region.Rotate) end,
  2806. get = function() return data.animation.start.rotateFunc and data.animation.start.rotateFunc:sub(8); end,
  2807. set = function(info, v) data.animation.start.rotateFunc = "return "..(v or ""); WeakAuras.Add(data); end
  2808. },
  2809. start_rotateFunc_expand = {
  2810. type = "execute",
  2811. order = 47.4,
  2812. name = L["Expand Text Editor"],
  2813. func = function()
  2814. WeakAuras.TextEditor(data, {"animation", "start", "rotateFunc"}, nil, true)
  2815. end,
  2816. hidden = function() return data.animation.start.type ~= "custom" or data.animation.start.rotateType ~= "custom" or not (data.animation.start.use_rotate and WeakAuras.regions[id].region.Rotate) end,
  2817. },
  2818. start_rotateFuncError = {
  2819. type = "description",
  2820. name = function()
  2821. if not(data.animation.start.rotateFunc) then
  2822. return "";
  2823. end
  2824. local _, errorString = loadstring(data.animation.start.rotateFunc or "");
  2825. return errorString and "|cFFFF0000"..errorString or "";
  2826. end,
  2827. width = "double",
  2828. order = 47.6,
  2829. hidden = function()
  2830. if(data.animation.start.type ~= "custom" or data.animation.start.rotateType ~= "custom" or not (data.animation.start.use_rotate and WeakAuras.regions[id].region.Rotate)) then
  2831. return true;
  2832. else
  2833. local loadedFunction, errorString = loadstring(data.animation.start.rotateFunc or "");
  2834. if(errorString and not loadedFunction) then
  2835. return false;
  2836. else
  2837. return true;
  2838. end
  2839. end
  2840. end
  2841. },
  2842. start_rotate = {
  2843. type = "range",
  2844. name = L["Angle"],
  2845. width = "double",
  2846. order = 48,
  2847. softMin = 0,
  2848. softMax = 360,
  2849. bigStep = 3,
  2850. hidden = function() return (data.animation.start.type ~= "custom" or not WeakAuras.regions[id].region.Rotate) end
  2851. },
  2852. start_use_color = {
  2853. type = "toggle",
  2854. name = L["Color"],
  2855. order = 48.2,
  2856. hidden = function() return (data.animation.start.type ~= "custom" or not WeakAuras.regions[id].region.Color) end
  2857. },
  2858. start_colorType = {
  2859. type = "select",
  2860. name = L["Type"],
  2861. order = 48.5,
  2862. values = anim_color_types,
  2863. hidden = function() return (data.animation.start.type ~= "custom" or not WeakAuras.regions[id].region.Color) end
  2864. },
  2865. start_colorFunc = {
  2866. type = "input",
  2867. multiline = true,
  2868. name = L["Custom Function"],
  2869. width = "normal",
  2870. order = 48.7,
  2871. hidden = function() return data.animation.start.type ~= "custom" or data.animation.start.colorType ~= "custom" or not (data.animation.start.use_color and WeakAuras.regions[id].region.Color) end,
  2872. get = function() return data.animation.start.colorFunc and data.animation.start.colorFunc:sub(8); end,
  2873. set = function(info, v) data.animation.start.colorFunc = "return "..(v or ""); WeakAuras.Add(data); end
  2874. },
  2875. start_colorFunc_expand = {
  2876. type = "execute",
  2877. order = 48.8,
  2878. name = L["Expand Text Editor"],
  2879. func = function()
  2880. WeakAuras.TextEditor(data, {"animation", "start", "colorFunc"}, nil, true)
  2881. end,
  2882. hidden = function() return data.animation.start.type ~= "custom" or data.animation.start.colorType ~= "custom" or not (data.animation.start.use_color and WeakAuras.regions[id].region.Color) end,
  2883. },
  2884. start_colorFuncError = {
  2885. type = "description",
  2886. name = function()
  2887. if not(data.animation.start.colorFunc) then
  2888. return "";
  2889. end
  2890. local _, errorString = loadstring(data.animation.start.colorFunc or "");
  2891. return errorString and "|cFFFF0000"..errorString or "";
  2892. end,
  2893. width = "double",
  2894. order = 49,
  2895. hidden = function()
  2896. if(data.animation.start.type ~= "custom" or data.animation.start.colorType ~= "custom" or not (data.animation.start.use_color and WeakAuras.regions[id].region.Color)) then
  2897. return true;
  2898. else
  2899. local loadedFunction, errorString = loadstring(data.animation.start.colorFunc or "");
  2900. if(errorString and not loadedFunction) then
  2901. return false;
  2902. else
  2903. return true;
  2904. end
  2905. end
  2906. end
  2907. },
  2908. start_color = {
  2909. type = "color",
  2910. name = L["Color"],
  2911. width = "double",
  2912. order = 49.5,
  2913. hidden = function() return (data.animation.start.type ~= "custom" or not WeakAuras.regions[id].region.Color) end,
  2914. get = function()
  2915. return data.animation.start.colorR,
  2916. data.animation.start.colorG,
  2917. data.animation.start.colorB,
  2918. data.animation.start.colorA;
  2919. end,
  2920. set = function(info, r, g, b, a)
  2921. data.animation.start.colorR = r;
  2922. data.animation.start.colorG = g;
  2923. data.animation.start.colorB = b;
  2924. data.animation.start.colorA = a;
  2925. end
  2926. },
  2927. main_header = {
  2928. type = "header",
  2929. name = L["Main"],
  2930. order = 50
  2931. },
  2932. main_type = {
  2933. type = "select",
  2934. name = L["Type"],
  2935. order = 52,
  2936. values = anim_types,
  2937. disabled = false
  2938. },
  2939. main_preset = {
  2940. type = "select",
  2941. name = L["Preset"],
  2942. order = 53,
  2943. values = function() return filterAnimPresetTypes(anim_main_preset_types, id) end,
  2944. hidden = function() return data.animation.main.type ~= "preset" end
  2945. },
  2946. main_duration_type_no_choice = {
  2947. type = "select",
  2948. name = L["Time in"],
  2949. order = 53,
  2950. width = "half",
  2951. values = duration_types_no_choice,
  2952. disabled = true,
  2953. hidden = function() return data.animation.main.type ~= "custom" or WeakAuras.CanHaveDuration(data) end,
  2954. get = function() return "seconds" end
  2955. },
  2956. main_duration_type = {
  2957. type = "select",
  2958. name = L["Time in"],
  2959. order = 53,
  2960. width = "half",
  2961. values = duration_types,
  2962. hidden = function() return data.animation.main.type ~= "custom" or not WeakAuras.CanHaveDuration(data) end
  2963. },
  2964. main_duration = {
  2965. type = "input",
  2966. name = function()
  2967. if(data.animation.main.duration_type == "relative") then
  2968. return L["% of Progress"];
  2969. else
  2970. return L["Duration (s)"];
  2971. end
  2972. end,
  2973. desc = function()
  2974. if(data.animation.main.duration_type == "relative") then
  2975. return L["Animation relative duration description"];
  2976. else
  2977. local ret = "";
  2978. ret = ret..L["The duration of the animation in seconds."].."\n";
  2979. ret = ret..L["Unlike the start or finish animations, the main animation will loop over and over until the display is hidden."]
  2980. return ret;
  2981. end
  2982. end,
  2983. order = 53.5,
  2984. width = "half",
  2985. hidden = function() return data.animation.main.type ~= "custom" end
  2986. },
  2987. main_use_alpha = {
  2988. type = "toggle",
  2989. name = L["Fade"],
  2990. order = 54,
  2991. hidden = function() return data.animation.main.type ~= "custom" end
  2992. },
  2993. main_alphaType = {
  2994. type = "select",
  2995. name = L["Type"],
  2996. order = 55,
  2997. values = anim_alpha_types,
  2998. hidden = function() return data.animation.main.type ~= "custom" end
  2999. },
  3000. main_alphaFunc = {
  3001. type = "input",
  3002. multiline = true,
  3003. name = L["Custom Function"],
  3004. width = "normal",
  3005. order = 55.3,
  3006. hidden = function() return data.animation.main.type ~= "custom" or data.animation.main.alphaType ~= "custom" or not data.animation.main.use_alpha end,
  3007. get = function() return data.animation.main.alphaFunc and data.animation.main.alphaFunc:sub(8); end,
  3008. set = function(info, v) data.animation.main.alphaFunc = "return "..(v or ""); WeakAuras.Add(data); end
  3009. },
  3010. main_alphaFunc_expand = {
  3011. type = "execute",
  3012. order = 55.4,
  3013. name = L["Expand Text Editor"],
  3014. func = function()
  3015. WeakAuras.TextEditor(data, {"animation", "main", "alphaFunc"}, nil, true)
  3016. end,
  3017. hidden = function() return data.animation.main.type ~= "custom" or data.animation.main.alphaType ~= "custom" or not data.animation.main.use_alpha end,
  3018. },
  3019. main_alphaFuncError = {
  3020. type = "description",
  3021. name = function()
  3022. if not(data.animation.main.alphaFunc) then
  3023. return "";
  3024. end
  3025. local _, errorString = loadstring(data.animation.main.alphaFunc or "");
  3026. return errorString and "|cFFFF0000"..errorString or "";
  3027. end,
  3028. width = "double",
  3029. order = 55.6,
  3030. hidden = function()
  3031. if(data.animation.main.type ~= "custom" or data.animation.main.alphaType ~= "custom" or not data.animation.main.use_alpha) then
  3032. return true;
  3033. else
  3034. local loadedFunction, errorString = loadstring(data.animation.main.alphaFunc or "");
  3035. if(errorString and not loadedFunction) then
  3036. return false;
  3037. else
  3038. return true;
  3039. end
  3040. end
  3041. end
  3042. },
  3043. main_alpha = {
  3044. type = "range",
  3045. name = L["Alpha"],
  3046. width = "double",
  3047. order = 56,
  3048. min = 0,
  3049. max = 1,
  3050. bigStep = 0.01,
  3051. isPercent = true,
  3052. hidden = function() return data.animation.main.type ~= "custom" end
  3053. },
  3054. main_use_translate = {
  3055. type = "toggle",
  3056. name = L["Slide"],
  3057. order = 58,
  3058. hidden = function() return data.animation.main.type ~= "custom" end
  3059. },
  3060. main_translateType = {
  3061. type = "select",
  3062. name = L["Type"],
  3063. order = 59,
  3064. values = anim_translate_types,
  3065. hidden = function() return data.animation.main.type ~= "custom" end
  3066. },
  3067. main_translateFunc = {
  3068. type = "input",
  3069. multiline = true,
  3070. name = L["Custom Function"],
  3071. width = "normal",
  3072. order = 59.3,
  3073. hidden = function() return data.animation.main.type ~= "custom" or data.animation.main.translateType ~= "custom" or not data.animation.main.use_translate end,
  3074. get = function() return data.animation.main.translateFunc and data.animation.main.translateFunc:sub(8); end,
  3075. set = function(info, v) data.animation.main.translateFunc = "return "..(v or ""); WeakAuras.Add(data); end
  3076. },
  3077. main_translateFunc_expand = {
  3078. type = "execute",
  3079. order = 59.4,
  3080. name = L["Expand Text Editor"],
  3081. func = function()
  3082. WeakAuras.TextEditor(data, {"animation", "main", "translateFunc"}, nil, true)
  3083. end,
  3084. hidden = function() return data.animation.main.type ~= "custom" or data.animation.main.translateType ~= "custom" or not data.animation.main.use_translate end,
  3085. },
  3086. main_translateFuncError = {
  3087. type = "description",
  3088. name = function()
  3089. if not(data.animation.main.translateFunc) then
  3090. return "";
  3091. end
  3092. local _, errorString = loadstring(data.animation.main.translateFunc or "");
  3093. return errorString and "|cFFFF0000"..errorString or "";
  3094. end,
  3095. width = "double",
  3096. order = 59.6,
  3097. hidden = function()
  3098. if(data.animation.main.type ~= "custom" or data.animation.main.translateType ~= "custom" or not data.animation.main.use_translate) then
  3099. return true;
  3100. else
  3101. local loadedFunction, errorString = loadstring(data.animation.main.translateFunc or "");
  3102. if(errorString and not loadedFunction) then
  3103. return false;
  3104. else
  3105. return true;
  3106. end
  3107. end
  3108. end
  3109. },
  3110. main_x = {
  3111. type = "range",
  3112. name = L["X Offset"],
  3113. order = 60,
  3114. softMin = -200,
  3115. softMax = 200,
  3116. step = 1,
  3117. bigStep = 5,
  3118. hidden = function() return data.animation.main.type ~= "custom" end
  3119. },
  3120. main_y = {
  3121. type = "range",
  3122. name = L["Y Offset"],
  3123. order = 61,
  3124. softMin = -200,
  3125. softMax = 200,
  3126. step = 1,
  3127. bigStep = 5,
  3128. hidden = function() return data.animation.main.type ~= "custom" end
  3129. },
  3130. main_use_scale = {
  3131. type = "toggle",
  3132. name = L["Zoom"],
  3133. order = 62,
  3134. hidden = function() return (data.animation.main.type ~= "custom" or not WeakAuras.regions[id].region.Scale) end
  3135. },
  3136. main_scaleType = {
  3137. type = "select",
  3138. name = L["Type"],
  3139. order = 63,
  3140. values = anim_scale_types,
  3141. hidden = function() return (data.animation.main.type ~= "custom" or not WeakAuras.regions[id].region.Scale) end
  3142. },
  3143. main_scaleFunc = {
  3144. type = "input",
  3145. multiline = true,
  3146. name = L["Custom Function"],
  3147. width = "normal",
  3148. order = 63.3,
  3149. hidden = function() return data.animation.main.type ~= "custom" or data.animation.main.scaleType ~= "custom" or not (data.animation.main.use_scale and WeakAuras.regions[id].region.Scale) end,
  3150. get = function() return data.animation.main.scaleFunc and data.animation.main.scaleFunc:sub(8); end,
  3151. set = function(info, v) data.animation.main.scaleFunc = "return "..(v or ""); WeakAuras.Add(data); end
  3152. },
  3153. main_scaleFunc_expand = {
  3154. type = "execute",
  3155. order = 63.4,
  3156. name = L["Expand Text Editor"],
  3157. func = function()
  3158. WeakAuras.TextEditor(data, {"animation", "main", "scaleFunc"}, nil, true)
  3159. end,
  3160. hidden = function() return data.animation.main.type ~= "custom" or data.animation.main.scaleType ~= "custom" or not (data.animation.main.use_scale and WeakAuras.regions[id].region.Scale) end,
  3161. },
  3162. main_scaleFuncError = {
  3163. type = "description",
  3164. name = function()
  3165. if not(data.animation.main.scaleFunc) then
  3166. return "";
  3167. end
  3168. local _, errorString = loadstring(data.animation.main.scaleFunc or "");
  3169. return errorString and "|cFFFF0000"..errorString or "";
  3170. end,
  3171. width = "double",
  3172. order = 63.6,
  3173. hidden = function()
  3174. if(data.animation.main.type ~= "custom" or data.animation.main.scaleType ~= "custom" or not (data.animation.main.use_scale and WeakAuras.regions[id].region.Scale)) then
  3175. return true;
  3176. else
  3177. local loadedFunction, errorString = loadstring(data.animation.main.scaleFunc or "");
  3178. if(errorString and not loadedFunction) then
  3179. return false;
  3180. else
  3181. return true;
  3182. end
  3183. end
  3184. end
  3185. },
  3186. main_scalex = {
  3187. type = "range",
  3188. name = L["X Scale"],
  3189. order = 64,
  3190. softMin = 0,
  3191. softMax = 5,
  3192. step = 0.01,
  3193. bigStep = 0.1,
  3194. hidden = function() return (data.animation.main.type ~= "custom" or not WeakAuras.regions[id].region.Scale) end
  3195. },
  3196. main_scaley = {
  3197. type = "range",
  3198. name = L["Y Scale"],
  3199. order = 65,
  3200. softMin = 0,
  3201. softMax = 5,
  3202. step = 0.01,
  3203. bigStep = 0.1,
  3204. hidden = function() return (data.animation.main.type ~= "custom" or not WeakAuras.regions[id].region.Scale) end
  3205. },
  3206. main_use_rotate = {
  3207. type = "toggle",
  3208. name = L["Rotate"],
  3209. order = 66,
  3210. hidden = function() return (data.animation.main.type ~= "custom" or not WeakAuras.regions[id].region.Rotate) end
  3211. },
  3212. main_rotateType = {
  3213. type = "select",
  3214. name = L["Type"],
  3215. order = 67,
  3216. values = anim_rotate_types,
  3217. hidden = function() return (data.animation.main.type ~= "custom" or not WeakAuras.regions[id].region.Rotate) end
  3218. },
  3219. main_rotateFunc = {
  3220. type = "input",
  3221. multiline = true,
  3222. name = L["Custom Function"],
  3223. width = "normal",
  3224. order = 67.3,
  3225. hidden = function() return data.animation.main.type ~= "custom" or data.animation.main.rotateType ~= "custom" or not (data.animation.main.use_rotate and WeakAuras.regions[id].region.Rotate) end,
  3226. get = function() return data.animation.main.rotateFunc and data.animation.main.rotateFunc:sub(8); end,
  3227. set = function(info, v) data.animation.main.rotateFunc = "return "..(v or ""); WeakAuras.Add(data); end
  3228. },
  3229. main_rotateFunc_expand = {
  3230. type = "execute",
  3231. order = 67.4,
  3232. name = L["Expand Text Editor"],
  3233. func = function()
  3234. WeakAuras.TextEditor(data, {"animation", "main", "rotateFunc"}, nil, true)
  3235. end,
  3236. hidden = function() return data.animation.main.type ~= "custom" or data.animation.main.rotateType ~= "custom" or not (data.animation.main.use_rotate and WeakAuras.regions[id].region.Rotate) end,
  3237. },
  3238. main_rotateFuncError = {
  3239. type = "description",
  3240. name = function()
  3241. if not(data.animation.main.rotateFunc) then
  3242. return "";
  3243. end
  3244. local _, errorString = loadstring(data.animation.main.rotateFunc or "");
  3245. return errorString and "|cFFFF0000"..errorString or "";
  3246. end,
  3247. width = "double",
  3248. order = 67.6,
  3249. hidden = function()
  3250. if(data.animation.main.type ~= "custom" or data.animation.main.rotateType ~= "custom" or not (data.animation.main.use_rotate and WeakAuras.regions[id].region.Rotate)) then
  3251. return true;
  3252. else
  3253. local loadedFunction, errorString = loadstring(data.animation.main.rotateFunc or "");
  3254. if(errorString and not loadedFunction) then
  3255. return false;
  3256. else
  3257. return true;
  3258. end
  3259. end
  3260. end
  3261. },
  3262. main_rotate = {
  3263. type = "range",
  3264. name = L["Angle"],
  3265. width = "double",
  3266. order = 68,
  3267. softMin = 0,
  3268. softMax = 360,
  3269. bigStep = 3,
  3270. hidden = function() return (data.animation.main.type ~= "custom" or not WeakAuras.regions[id].region.Rotate) end
  3271. },
  3272. main_use_color = {
  3273. type = "toggle",
  3274. name = L["Color"],
  3275. order = 68.2,
  3276. hidden = function() return (data.animation.main.type ~= "custom" or not WeakAuras.regions[id].region.Color) end
  3277. },
  3278. main_colorType = {
  3279. type = "select",
  3280. name = L["Type"],
  3281. order = 68.5,
  3282. values = anim_color_types,
  3283. hidden = function() return (data.animation.main.type ~= "custom" or not WeakAuras.regions[id].region.Color) end
  3284. },
  3285. main_colorFunc = {
  3286. type = "input",
  3287. multiline = true,
  3288. name = L["Custom Function"],
  3289. width = "normal",
  3290. order = 68.7,
  3291. hidden = function() return data.animation.main.type ~= "custom" or data.animation.main.colorType ~= "custom" or not (data.animation.main.use_color and WeakAuras.regions[id].region.Color) end,
  3292. get = function() return data.animation.main.colorFunc and data.animation.main.colorFunc:sub(8); end,
  3293. set = function(info, v) data.animation.main.colorFunc = "return "..(v or ""); WeakAuras.Add(data); end
  3294. },
  3295. main_colorFunc_expand = {
  3296. type = "execute",
  3297. order = 68.8,
  3298. name = L["Expand Text Editor"],
  3299. func = function()
  3300. WeakAuras.TextEditor(data, {"animation", "main", "colorFunc"}, nil, true)
  3301. end,
  3302. hidden = function() return data.animation.main.type ~= "custom" or data.animation.main.colorType ~= "custom" or not (data.animation.main.use_color and WeakAuras.regions[id].region.Color) end,
  3303. },
  3304. main_colorFuncError = {
  3305. type = "description",
  3306. name = function()
  3307. if not(data.animation.main.colorFunc) then
  3308. return "";
  3309. end
  3310. local _, errorString = loadstring(data.animation.main.colorFunc or "");
  3311. return errorString and "|cFFFF0000"..errorString or "";
  3312. end,
  3313. width = "double",
  3314. order = 69,
  3315. hidden = function()
  3316. if(data.animation.main.type ~= "custom" or data.animation.main.colorType ~= "custom" or not (data.animation.main.use_color and WeakAuras.regions[id].region.Color)) then
  3317. return true;
  3318. else
  3319. local loadedFunction, errorString = loadstring(data.animation.main.colorFunc or "");
  3320. if(errorString and not loadedFunction) then
  3321. return false;
  3322. else
  3323. return true;
  3324. end
  3325. end
  3326. end
  3327. },
  3328. main_color = {
  3329. type = "color",
  3330. name = L["Color"],
  3331. width = "double",
  3332. order = 69.5,
  3333. hidden = function() return (data.animation.main.type ~= "custom" or not WeakAuras.regions[id].region.Color) end,
  3334. get = function()
  3335. return data.animation.main.colorR,
  3336. data.animation.main.colorG,
  3337. data.animation.main.colorB,
  3338. data.animation.main.colorA;
  3339. end,
  3340. set = function(info, r, g, b, a)
  3341. data.animation.main.colorR = r;
  3342. data.animation.main.colorG = g;
  3343. data.animation.main.colorB = b;
  3344. data.animation.main.colorA = a;
  3345. end
  3346. },
  3347. finish_header = {
  3348. type = "header",
  3349. name = L["Finish"],
  3350. order = 70
  3351. },
  3352. finish_type = {
  3353. type = "select",
  3354. name = L["Type"],
  3355. order = 72,
  3356. values = anim_types,
  3357. disabled = false
  3358. },
  3359. finish_preset = {
  3360. type = "select",
  3361. name = L["Preset"],
  3362. order = 73,
  3363. values = function() return filterAnimPresetTypes(anim_finish_preset_types, id) end,
  3364. hidden = function() return data.animation.finish.type ~= "preset" end
  3365. },
  3366. finish_duration_type_no_choice = {
  3367. type = "select",
  3368. name = L["Time in"],
  3369. order = 73,
  3370. width = "half",
  3371. values = duration_types_no_choice,
  3372. disabled = true,
  3373. hidden = function() return data.animation.finish.type ~= "custom" end,
  3374. get = function() return "seconds" end
  3375. },
  3376. finish_duration = {
  3377. type = "input",
  3378. name = L["Duration (s)"],
  3379. desc = "The duration of the animation in seconds.\n\nThe finish animation does not start playing until after the display would normally be hidden.",
  3380. order = 73.5,
  3381. width = "half",
  3382. hidden = function() return data.animation.finish.type ~= "custom" end
  3383. },
  3384. finish_use_alpha = {
  3385. type = "toggle",
  3386. name = L["Fade Out"],
  3387. order = 74,
  3388. hidden = function() return data.animation.finish.type ~= "custom" end
  3389. },
  3390. finish_alphaType = {
  3391. type = "select",
  3392. name = L["Type"],
  3393. order = 75,
  3394. values = anim_alpha_types,
  3395. hidden = function() return data.animation.finish.type ~= "custom" end
  3396. },
  3397. finish_alphaFunc = {
  3398. type = "input",
  3399. multiline = true,
  3400. name = L["Custom Function"],
  3401. width = "normal",
  3402. order = 75.3,
  3403. hidden = function() return data.animation.finish.type ~= "custom" or data.animation.finish.alphaType ~= "custom" or not data.animation.finish.use_alpha end,
  3404. get = function() return data.animation.finish.alphaFunc and data.animation.finish.alphaFunc:sub(8); end,
  3405. set = function(info, v) data.animation.finish.alphaFunc = "return "..(v or ""); WeakAuras.Add(data); end
  3406. },
  3407. finish_alphaFunc_expand = {
  3408. type = "execute",
  3409. order = 75.4,
  3410. name = L["Expand Text Editor"],
  3411. func = function()
  3412. WeakAuras.TextEditor(data, {"animation", "finish", "alphaFunc"}, nil, true)
  3413. end,
  3414. hidden = function() return data.animation.finish.type ~= "custom" or data.animation.finish.alphaType ~= "custom" or not data.animation.finish.use_alpha end,
  3415. },
  3416. finish_alphaFuncError = {
  3417. type = "description",
  3418. name = function()
  3419. if not(data.animation.finish.alphaFunc) then
  3420. return "";
  3421. end
  3422. local _, errorString = loadstring(data.animation.finish.alphaFunc or "");
  3423. return errorString and "|cFFFF0000"..errorString or "";
  3424. end,
  3425. width = "double",
  3426. order = 75.6,
  3427. hidden = function()
  3428. if(data.animation.finish.type ~= "custom" or data.animation.finish.alphaType ~= "custom" or not data.animation.finish.use_alpha) then
  3429. return true;
  3430. else
  3431. local loadedFunction, errorString = loadstring(data.animation.finish.alphaFunc or "");
  3432. if(errorString and not loadedFunction) then
  3433. return false;
  3434. else
  3435. return true;
  3436. end
  3437. end
  3438. end
  3439. },
  3440. finish_alpha = {
  3441. type = "range",
  3442. name = L["Alpha"],
  3443. width = "double",
  3444. order = 76,
  3445. min = 0,
  3446. max = 1,
  3447. bigStep = 0.01,
  3448. isPercent = true,
  3449. hidden = function() return data.animation.finish.type ~= "custom" end
  3450. },
  3451. finish_use_translate = {
  3452. type = "toggle",
  3453. name = L["Slide Out"],
  3454. order = 78,
  3455. hidden = function() return data.animation.finish.type ~= "custom" end
  3456. },
  3457. finish_translateType = {
  3458. type = "select",
  3459. name = L["Type"],
  3460. order = 79,
  3461. values = anim_translate_types,
  3462. hidden = function() return data.animation.finish.type ~= "custom" end
  3463. },
  3464. finish_translateFunc = {
  3465. type = "input",
  3466. multiline = true,
  3467. name = L["Custom Function"],
  3468. width = "normal",
  3469. order = 79.3,
  3470. hidden = function() return data.animation.finish.type ~= "custom" or data.animation.finish.translateType ~= "custom" or not data.animation.finish.use_translate end,
  3471. get = function() return data.animation.finish.translateFunc and data.animation.finish.translateFunc:sub(8); end,
  3472. set = function(info, v) data.animation.finish.translateFunc = "return "..(v or ""); WeakAuras.Add(data); end
  3473. },
  3474. finish_translateFunc_expand = {
  3475. type = "execute",
  3476. order = 79.4,
  3477. name = L["Expand Text Editor"],
  3478. func = function()
  3479. WeakAuras.TextEditor(data, {"animation", "finish", "translateFunc"}, nil, true)
  3480. end,
  3481. hidden = function() return data.animation.finish.type ~= "custom" or data.animation.finish.translateType ~= "custom" or not data.animation.finish.use_translate end,
  3482. },
  3483. finish_translateFuncError = {
  3484. type = "description",
  3485. name = function()
  3486. if not(data.animation.finish.translateFunc) then
  3487. return "";
  3488. end
  3489. local _, errorString = loadstring(data.animation.finish.translateFunc or "");
  3490. return errorString and "|cFFFF0000"..errorString or "";
  3491. end,
  3492. width = "double",
  3493. order = 79.6,
  3494. hidden = function()
  3495. if(data.animation.finish.type ~= "custom" or data.animation.finish.translateType ~= "custom" or not data.animation.finish.use_translate) then
  3496. return true;
  3497. else
  3498. local loadedFunction, errorString = loadstring(data.animation.finish.translateFunc or "");
  3499. if(errorString and not loadedFunction) then
  3500. return false;
  3501. else
  3502. return true;
  3503. end
  3504. end
  3505. end
  3506. },
  3507. finish_x = {
  3508. type = "range",
  3509. name = L["X Offset"],
  3510. order = 80,
  3511. softMin = -200,
  3512. softMax = 200,
  3513. step = 1,
  3514. bigStep = 5,
  3515. hidden = function() return data.animation.finish.type ~= "custom" end
  3516. },
  3517. finish_y = {
  3518. type = "range",
  3519. name = L["Y Offset"],
  3520. order = 81,
  3521. softMin = -200,
  3522. softMax = 200,
  3523. step = 1,
  3524. bigStep = 5,
  3525. hidden = function() return data.animation.finish.type ~= "custom" end
  3526. },
  3527. finish_use_scale = {
  3528. type = "toggle",
  3529. name = L["Zoom Out"],
  3530. order = 82,
  3531. hidden = function() return (data.animation.finish.type ~= "custom" or not WeakAuras.regions[id].region.Scale) end
  3532. },
  3533. finish_scaleType = {
  3534. type = "select",
  3535. name = L["Type"],
  3536. order = 83,
  3537. values = anim_scale_types,
  3538. hidden = function() return (data.animation.finish.type ~= "custom" or not WeakAuras.regions[id].region.Scale) end
  3539. },
  3540. finish_scaleFunc = {
  3541. type = "input",
  3542. multiline = true,
  3543. name = L["Custom Function"],
  3544. width = "normal",
  3545. order = 83.3,
  3546. hidden = function() return data.animation.finish.type ~= "custom" or data.animation.finish.scaleType ~= "custom" or not (data.animation.finish.use_scale and WeakAuras.regions[id].region.Scale) end,
  3547. get = function() return data.animation.finish.scaleFunc and data.animation.finish.scaleFunc:sub(8); end,
  3548. set = function(info, v) data.animation.finish.scaleFunc = "return "..(v or ""); WeakAuras.Add(data); end
  3549. },
  3550. finish_scaleFunc_expand = {
  3551. type = "execute",
  3552. order = 83.4,
  3553. name = L["Expand Text Editor"],
  3554. func = function()
  3555. WeakAuras.TextEditor(data, {"animation", "finish", "scaleFunc"}, nil, true)
  3556. end,
  3557. hidden = function() return data.animation.finish.type ~= "custom" or data.animation.finish.scaleType ~= "custom" or not (data.animation.finish.use_scale and WeakAuras.regions[id].region.Scale) end,
  3558. },
  3559. finish_scaleFuncError = {
  3560. type = "description",
  3561. name = function()
  3562. if not(data.animation.finish.scaleFunc) then
  3563. return "";
  3564. end
  3565. local _, errorString = loadstring(data.animation.finish.scaleFunc or "");
  3566. return errorString and "|cFFFF0000"..errorString or "";
  3567. end,
  3568. width = "double",
  3569. order = 83.6,
  3570. hidden = function()
  3571. if(data.animation.finish.type ~= "custom" or data.animation.finish.scaleType ~= "custom" or not (data.animation.finish.use_scale and WeakAuras.regions[id].region.Scale)) then
  3572. return true;
  3573. else
  3574. local loadedFunction, errorString = loadstring(data.animation.finish.scaleFunc or "");
  3575. if(errorString and not loadedFunction) then
  3576. return false;
  3577. else
  3578. return true;
  3579. end
  3580. end
  3581. end
  3582. },
  3583. finish_scalex = {
  3584. type = "range",
  3585. name = L["X Scale"],
  3586. order = 84,
  3587. softMin = 0,
  3588. softMax = 5,
  3589. step = 0.01,
  3590. bigStep = 0.1,
  3591. hidden = function() return (data.animation.finish.type ~= "custom" or not WeakAuras.regions[id].region.Scale) end
  3592. },
  3593. finish_scaley = {
  3594. type = "range",
  3595. name = L["Y Scale"],
  3596. order = 85,
  3597. softMin = 0,
  3598. softMax = 5,
  3599. step = 0.01,
  3600. bigStep = 0.1,
  3601. hidden = function() return (data.animation.finish.type ~= "custom" or not WeakAuras.regions[id].region.Scale) end
  3602. },
  3603. finish_use_rotate = {
  3604. type = "toggle",
  3605. name = L["Rotate Out"],
  3606. order = 86,
  3607. hidden = function() return (data.animation.finish.type ~= "custom" or not WeakAuras.regions[id].region.Rotate) end
  3608. },
  3609. finish_rotateType = {
  3610. type = "select",
  3611. name = L["Type"],
  3612. order = 87,
  3613. values = anim_rotate_types,
  3614. hidden = function() return (data.animation.finish.type ~= "custom" or not WeakAuras.regions[id].region.Rotate) end
  3615. },
  3616. finish_rotateFunc = {
  3617. type = "input",
  3618. multiline = true,
  3619. name = L["Custom Function"],
  3620. width = "normal",
  3621. order = 87.3,
  3622. hidden = function() return data.animation.finish.type ~= "custom" or data.animation.finish.rotateType ~= "custom" or not (data.animation.finish.use_rotate and WeakAuras.regions[id].region.Rotate) end,
  3623. get = function() return data.animation.finish.rotateFunc and data.animation.finish.rotateFunc:sub(8); end,
  3624. set = function(info, v) data.animation.finish.rotateFunc = "return "..(v or ""); WeakAuras.Add(data); end
  3625. },
  3626. finish_rotateFunc_expand = {
  3627. type = "execute",
  3628. order = 87.4,
  3629. name = L["Expand Text Editor"],
  3630. func = function()
  3631. WeakAuras.TextEditor(data, {"animation", "finish", "rotateFunc"}, nil, true)
  3632. end,
  3633. hidden = function() return data.animation.finish.type ~= "custom" or data.animation.finish.rotateType ~= "custom" or not (data.animation.finish.use_rotate and WeakAuras.regions[id].region.Rotate) end,
  3634. },
  3635. finish_rotateFuncError = {
  3636. type = "description",
  3637. name = function()
  3638. if not(data.animation.finish.rotateFunc) then
  3639. return "";
  3640. end
  3641. local _, errorString = loadstring(data.animation.finish.rotateFunc or "");
  3642. return errorString and "|cFFFF0000"..errorString or "";
  3643. end,
  3644. width = "double",
  3645. order = 87.6,
  3646. hidden = function()
  3647. if(data.animation.finish.type ~= "custom" or data.animation.finish.rotateType ~= "custom" or not (data.animation.finish.use_rotate and WeakAuras.regions[id].region.Rotate)) then
  3648. return true;
  3649. else
  3650. local loadedFunction, errorString = loadstring(data.animation.finish.rotateFunc or "");
  3651. if(errorString and not loadedFunction) then
  3652. return false;
  3653. else
  3654. return true;
  3655. end
  3656. end
  3657. end
  3658. },
  3659. finish_rotate = {
  3660. type = "range",
  3661. name = L["Angle"],
  3662. width = "double",
  3663. order = 88,
  3664. softMin = 0,
  3665. softMax = 360,
  3666. bigStep = 3,
  3667. hidden = function() return (data.animation.finish.type ~= "custom" or not WeakAuras.regions[id].region.Rotate) end
  3668. },
  3669. finish_use_color = {
  3670. type = "toggle",
  3671. name = L["Color"],
  3672. order = 88.2,
  3673. hidden = function() return (data.animation.finish.type ~= "custom" or not WeakAuras.regions[id].region.Color) end
  3674. },
  3675. finish_colorType = {
  3676. type = "select",
  3677. name = L["Type"],
  3678. order = 88.5,
  3679. values = anim_color_types,
  3680. hidden = function() return (data.animation.finish.type ~= "custom" or not WeakAuras.regions[id].region.Color) end
  3681. },
  3682. finish_colorFunc = {
  3683. type = "input",
  3684. multiline = true,
  3685. name = L["Custom Function"],
  3686. width = "normal",
  3687. order = 88.7,
  3688. hidden = function() return data.animation.finish.type ~= "custom" or data.animation.finish.colorType ~= "custom" or not (data.animation.finish.use_color and WeakAuras.regions[id].region.Color) end,
  3689. get = function() return data.animation.finish.colorFunc and data.animation.finish.colorFunc:sub(8); end,
  3690. set = function(info, v) data.animation.finish.colorFunc = "return "..(v or ""); WeakAuras.Add(data); end
  3691. },
  3692. finish_colorFunc_expand = {
  3693. type = "execute",
  3694. order = 88.8,
  3695. name = L["Expand Text Editor"],
  3696. func = function()
  3697. WeakAuras.TextEditor(data, {"animation", "finish", "colorFunc"}, nil, true)
  3698. end,
  3699. hidden = function() return data.animation.finish.type ~= "custom" or data.animation.finish.colorType ~= "custom" or not (data.animation.finish.use_color and WeakAuras.regions[id].region.Color) end,
  3700. },
  3701. finish_colorFuncError = {
  3702. type = "description",
  3703. name = function()
  3704. if not(data.animation.finish.colorFunc) then
  3705. return "";
  3706. end
  3707. local _, errorString = loadstring(data.animation.finish.colorFunc or "");
  3708. return errorString and "|cFFFF0000"..errorString or "";
  3709. end,
  3710. width = "double",
  3711. order = 89,
  3712. hidden = function()
  3713. if(data.animation.finish.type ~= "custom" or data.animation.finish.colorType ~= "custom" or not (data.animation.finish.use_color and WeakAuras.regions[id].region.Color)) then
  3714. return true;
  3715. else
  3716. local loadedFunction, errorString = loadstring(data.animation.finish.colorFunc or "");
  3717. if(errorString and not loadedFunction) then
  3718. return false;
  3719. else
  3720. return true;
  3721. end
  3722. end
  3723. end
  3724. },
  3725. finish_color = {
  3726. type = "color",
  3727. name = L["Color"],
  3728. width = "double",
  3729. order = 89.5,
  3730. hidden = function() return (data.animation.finish.type ~= "custom" or not WeakAuras.regions[id].region.Color) end,
  3731. get = function()
  3732. return data.animation.finish.colorR,
  3733. data.animation.finish.colorG,
  3734. data.animation.finish.colorB,
  3735. data.animation.finish.colorA;
  3736. end,
  3737. set = function(info, r, g, b, a)
  3738. data.animation.finish.colorR = r;
  3739. data.animation.finish.colorG = g;
  3740. data.animation.finish.colorB = b;
  3741. data.animation.finish.colorA = a;
  3742. end
  3743. }
  3744. }
  3745. }
  3746. }
  3747. };
  3748.  
  3749. WeakAuras.ReloadTriggerOptions(data);
  3750. end
  3751.  
  3752. function WeakAuras.EnsureOptions(id)
  3753. if not(displayOptions[id]) then
  3754. WeakAuras.AddOption(id, WeakAuras.GetData(id));
  3755. end
  3756. end
  3757.  
  3758. function WeakAuras.GetSpellTooltipText(id)
  3759. local tooltip = WeakAuras.GetHiddenTooltip();
  3760. tooltip:SetSpellByID(id);
  3761. local lines = { tooltip:GetRegions() };
  3762. local i = 1;
  3763. local tooltipText = "";
  3764. while(lines[i]) do
  3765. if(lines[i]:GetObjectType() == "FontString") then
  3766. if(lines[i]:GetText()) then
  3767. if(tooltipText == "") then
  3768. tooltipText = lines[i]:GetText();
  3769. else
  3770. tooltipText = tooltipText.." - "..lines[i]:GetText();
  3771. end
  3772. end
  3773. end
  3774. i = i + 1;
  3775. end
  3776. tooltipText = tooltipText or L["No tooltip text"];
  3777. return tooltipText;
  3778. end
  3779.  
  3780. function WeakAuras.ReloadTriggerOptions(data)
  3781. local id = data.id;
  3782. WeakAuras.EnsureOptions(id);
  3783.  
  3784. local trigger, untrigger, appendToTriggerPath, appendToUntriggerPath;
  3785. if(data.controlledChildren) then
  3786. optionTriggerChoices[id] = nil;
  3787. for index, childId in pairs(data.controlledChildren) do
  3788. if not(optionTriggerChoices[id]) then
  3789. optionTriggerChoices[id] = optionTriggerChoices[childId];
  3790. trigger = WeakAuras.GetData(childId).trigger;
  3791. untrigger = WeakAuras.GetData(childId).untrigger;
  3792. else
  3793. if(optionTriggerChoices[id] ~= optionTriggerChoices[childId]) then
  3794. trigger, untrigger = {}, {};
  3795. optionTriggerChoices[id] = -1;
  3796. break;
  3797. end
  3798. end
  3799. end
  3800.  
  3801. optionTriggerChoices[id] = optionTriggerChoices[id] or 0;
  3802.  
  3803. if(optionTriggerChoices[id] >= 0) then
  3804. for index, childId in pairs(data.controlledChildren) do
  3805. local childData = WeakAuras.GetData(childId);
  3806. if(childData) then
  3807. optionTriggerChoices[childId] = optionTriggerChoices[id];
  3808. WeakAuras.ReloadTriggerOptions(childData);
  3809. end
  3810. end
  3811. end
  3812. else
  3813. optionTriggerChoices[id] = optionTriggerChoices[id] or 0;
  3814. if(optionTriggerChoices[id] == 0) then
  3815. trigger = data.trigger;
  3816. untrigger = data.untrigger;
  3817.  
  3818. function appendToTriggerPath(...)
  3819. local ret = {...};
  3820. tinsert(ret, 1, "trigger");
  3821. return ret;
  3822. end
  3823.  
  3824. function appendToUntriggerPath(...)
  3825. local ret = {...};
  3826. tinsert(ret, 1, "untrigger");
  3827. return ret;
  3828. end
  3829. else
  3830. trigger = data.additional_triggers and data.additional_triggers[optionTriggerChoices[id]].trigger or data.trigger;
  3831. untrigger = data.additional_triggers and data.additional_triggers[optionTriggerChoices[id]].untrigger or data.untrigger;
  3832.  
  3833. function appendToTriggerPath(...)
  3834. local ret = {...};
  3835. tinsert(ret, 1, "trigger");
  3836. tinsert(ret, 1, optionTriggerChoices[id]);
  3837. tinsert(ret, 1, "additional_triggers");
  3838. return ret;
  3839. end
  3840.  
  3841. function appendToUntriggerPath(...)
  3842. local ret = {...};
  3843. tinsert(ret, 1, "untrigger");
  3844. tinsert(ret, 1, optionTriggerChoices[id]);
  3845. tinsert(ret, 1, "additional_triggers");
  3846. return ret;
  3847. end
  3848. end
  3849. end
  3850.  
  3851. local function getAuraMatchesLabel(name)
  3852. local ids = idCache[name]
  3853. if(ids) then
  3854. local descText = "";
  3855. local numMatches = 0;
  3856. for id, _ in pairs(ids) do
  3857. numMatches = numMatches + 1;
  3858. end
  3859. if(numMatches == 1) then
  3860. return L["1 Match"];
  3861. else
  3862. return L["%i Matches"]:format(numMatches);
  3863. end
  3864. else
  3865. return "";
  3866. end
  3867. end
  3868.  
  3869. -- the spell id table is sparse, so tremove doesn't work
  3870. local function spellId_tremove(tbl, pos)
  3871. for i = pos, 9, 1 do
  3872. tbl[i] = tbl[i + 1]
  3873. end
  3874. end
  3875.  
  3876. local function getAuraMatchesList(name)
  3877. local ids = idCache[name]
  3878. if(ids) then
  3879. local descText = "";
  3880. for id, _ in pairs(ids) do
  3881. local name, _, icon = GetSpellInfo(id);
  3882. if(icon) then
  3883. if(descText == "") then
  3884. descText = "|T"..icon..":0|t: "..id;
  3885. else
  3886. descText = descText.."\n|T"..icon..":0|t: "..id;
  3887. end
  3888. end
  3889. end
  3890. return descText;
  3891. else
  3892. return "";
  3893. end
  3894. end
  3895.  
  3896. local aura_options = {
  3897. fullscan = {
  3898. type = "toggle",
  3899. name = L["Use Full Scan (High CPU)"],
  3900. width = "double",
  3901. order = 9,
  3902. },
  3903. autoclone = {
  3904. type = "toggle",
  3905. name = L["Show all matches (Auto-clone)"],
  3906. width = "double",
  3907. hidden = function() return not (trigger.type == "aura" and trigger.fullscan); end,
  3908. set = function(info, v)
  3909. trigger.autoclone = v;
  3910. if(v == true) then
  3911. WeakAuras.ShowCloneDialog(data);
  3912. WeakAuras.UpdateCloneConfig(data);
  3913. else
  3914. WeakAuras.HideAllClones(data.id);
  3915. end
  3916. WeakAuras.Add(data);
  3917. end,
  3918. order = 9.5
  3919. },
  3920. useName = {
  3921. type = "toggle",
  3922. name = L["Aura(s)"],
  3923. width = "half",
  3924. order = 10,
  3925. hidden = function() return not (trigger.type == "aura" and not trigger.fullscan and trigger.unit ~= "multi"); end,
  3926. disabled = true,
  3927. get = function() return true end
  3928. },
  3929. use_name = {
  3930. type = "toggle",
  3931. name = L["Aura Name"],
  3932. order = 10,
  3933. hidden = function() return not (trigger.type == "aura" and trigger.fullscan); end
  3934. },
  3935. name_operator = {
  3936. type = "select",
  3937. name = L["Operator"],
  3938. order = 11,
  3939. disabled = function() return not trigger.use_name end,
  3940. hidden = function() return not (trigger.type == "aura" and trigger.fullscan); end,
  3941. values = WeakAuras.string_operator_types
  3942. },
  3943. name = {
  3944. type = "input",
  3945. name = L["Aura Name"],
  3946. width = "double",
  3947. order = 12,
  3948. disabled = function() return not trigger.use_name end,
  3949. hidden = function() return not (trigger.type == "aura" and trigger.fullscan); end
  3950. },
  3951. use_tooltip = {
  3952. type = "toggle",
  3953. name = L["Tooltip"],
  3954. order = 13,
  3955. hidden = function() return not (trigger.type == "aura" and trigger.fullscan and trigger.unit ~= "multi"); end
  3956. },
  3957. tooltip_operator = {
  3958. type = "select",
  3959. name = L["Operator"],
  3960. order = 14,
  3961. disabled = function() return not trigger.use_tooltip end,
  3962. hidden = function() return not (trigger.type == "aura" and trigger.fullscan and trigger.unit ~= "multi"); end,
  3963. values = WeakAuras.string_operator_types
  3964. },
  3965. tooltip = {
  3966. type = "input",
  3967. name = L["Tooltip"],
  3968. width = "double",
  3969. order = 15,
  3970. disabled = function() return not trigger.use_tooltip end,
  3971. hidden = function() return not (trigger.type == "aura" and trigger.fullscan and trigger.unit ~= "multi"); end
  3972. },
  3973. use_stealable = {
  3974. type = "toggle",
  3975. name = function(input)
  3976. local value = trigger.use_stealable;
  3977. if(value == nil) then return L["Stealable"];
  3978. elseif(value == false) then return "|cFFFF0000 "..L["Negator"].." "..L["Stealable"];
  3979. else return "|cFF00FF00"..L["Stealable"]; end
  3980. end,
  3981. width = "double",
  3982. order = 16,
  3983. hidden = function() return not (trigger.type == "aura" and trigger.fullscan and trigger.unit ~= "multi"); end,
  3984. get = function()
  3985. local value = trigger.use_stealable;
  3986. if(value == nil) then return false;
  3987. elseif(value == false) then return "false";
  3988. else return "true"; end
  3989. end,
  3990. set = function(info, v)
  3991. if(v) then
  3992. trigger.use_stealable = true;
  3993. else
  3994. local value = trigger.use_stealable;
  3995. if(value == false) then trigger.use_stealable = nil;
  3996. else trigger.use_stealable = false end
  3997. end
  3998. WeakAuras.Add(data);
  3999. WeakAuras.SetIconNames(data);
  4000. end
  4001. },
  4002. use_spellId = {
  4003. type = "toggle",
  4004. name = L["Spell ID"],
  4005. order = 17,
  4006. hidden = function() return not (trigger.type == "aura" and trigger.fullscan and trigger.unit ~= "multi"); end
  4007. },
  4008. spellId = {
  4009. type = "input",
  4010. name = L["Spell ID"],
  4011. order = 18,
  4012. disabled = function() return not trigger.use_spellId end,
  4013. hidden = function() return not (trigger.type == "aura" and trigger.fullscan and trigger.unit ~= "multi"); end
  4014. },
  4015. use_debuffClass = {
  4016. type = "toggle",
  4017. name = L["Debuff Type"],
  4018. order = 19,
  4019. hidden = function() return not (trigger.type == "aura" and trigger.fullscan); end
  4020. },
  4021. debuffClass = {
  4022. type = "select",
  4023. name = L["Debuff Type"],
  4024. order = 20,
  4025. disabled = function() return not trigger.use_debuffClass end,
  4026. hidden = function() return not (trigger.type == "aura" and trigger.fullscan); end,
  4027. values = WeakAuras.debuff_class_types
  4028. },
  4029. multiuse_name = {
  4030. type = "toggle",
  4031. name = L["Aura Name"],
  4032. width = "half",
  4033. order = 10,
  4034. hidden = function() return not (trigger.type == "aura" and not trigger.fullscan and trigger.unit == "multi"); end,
  4035. disabled = true,
  4036. get = function() return true end
  4037. },
  4038. multiicon = {
  4039. type = "execute",
  4040. name = "",
  4041. width = "half",
  4042. image = function() return trigger.name and iconCache[trigger.name] or "", 18, 18 end,
  4043. order = 11,
  4044. disabled = function() return not trigger.name and iconCache[trigger.name] end,
  4045. hidden = function() return not (trigger.type == "aura" and not trigger.fullscan and trigger.unit == "multi"); end
  4046. },
  4047. multiname = {
  4048. type = "input",
  4049. name = L["Aura Name"],
  4050. desc = L["Enter an aura name, partial aura name, or spell id"],
  4051. order = 12,
  4052. hidden = function() return not (trigger.type == "aura" and not trigger.fullscan and trigger.unit == "multi"); end,
  4053. get = function(info) return trigger.spellId and tostring(trigger.spellId) or trigger.name end,
  4054. set = function(info, v)
  4055. if(v == "") then
  4056. trigger.name = nil;
  4057. trigger.spellId = nil;
  4058. else
  4059. trigger.name, trigger.spellId = WeakAuras.CorrectAuraName(v);
  4060. end
  4061. WeakAuras.Add(data);
  4062. WeakAuras.SetThumbnail(data);
  4063. WeakAuras.SetIconNames(data);
  4064. WeakAuras.UpdateDisplayButton(data);
  4065. end,
  4066. },
  4067. name1icon = {
  4068. type = "execute",
  4069. name = function() return getAuraMatchesLabel(trigger.names[1]) end,
  4070. desc = function() return getAuraMatchesList(trigger.names[1]) end,
  4071. width = "half",
  4072. image = function() return iconCache[trigger.names[1]] or "", 18, 18 end,
  4073. order = 11,
  4074. disabled = function() return not iconCache[trigger.names[1]] end,
  4075. hidden = function() return not (trigger.type == "aura" and not trigger.fullscan and trigger.unit ~= "multi"); end
  4076. },
  4077. name1 = {
  4078. type = "input",
  4079. name = L["Aura Name"],
  4080. desc = L["Enter an aura name, partial aura name, or spell id"],
  4081. order = 12,
  4082. hidden = function() return not (trigger.type == "aura" and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4083. get = function(info) return trigger.spellIds[1] and tostring(trigger.spellIds[1]) or trigger.names[1] end,
  4084. set = function(info, v)
  4085. if(v == "") then
  4086. if(trigger.names[1]) then
  4087. tremove(trigger.names, 1);
  4088. spellId_tremove(trigger.spellIds, 1);
  4089. end
  4090. else
  4091. if(tonumber(v)) then
  4092. WeakAuras.ShowSpellIDDialog(trigger, v);
  4093. end
  4094. trigger.names[1], trigger.spellIds[1] = WeakAuras.CorrectAuraName(v);
  4095. end
  4096. WeakAuras.Add(data);
  4097. WeakAuras.SetThumbnail(data);
  4098. WeakAuras.SetIconNames(data);
  4099. WeakAuras.UpdateDisplayButton(data);
  4100. end,
  4101. },
  4102. name2space = {
  4103. type = "execute",
  4104. name = L["or"],
  4105. width = "half",
  4106. image = function() return "", 0, 0 end,
  4107. order = 13,
  4108. hidden = function() return not (trigger.type == "aura" and trigger.names[1] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4109. },
  4110. name2icon = {
  4111. type = "execute",
  4112. name = function() return getAuraMatchesLabel(trigger.names[2]) end,
  4113. desc = function() return getAuraMatchesList(trigger.names[2]) end,
  4114. width = "half",
  4115. image = function() return iconCache[trigger.names[2]] or "", 18, 18 end,
  4116. order = 14,
  4117. disabled = function() return not iconCache[trigger.names[2]] end,
  4118. hidden = function() return not (trigger.type == "aura" and trigger.names[1] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4119. },
  4120. name2 = {
  4121. type = "input",
  4122. order = 15,
  4123. name = "",
  4124. hidden = function() return not (trigger.type == "aura" and trigger.names[1] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4125. get = function(info) return trigger.spellIds[2] and tostring(trigger.spellIds[2]) or trigger.names[2] end,
  4126. set = function(info, v)
  4127. if(v == "") then
  4128. if(trigger.names[2]) then
  4129. tremove(trigger.names, 2);
  4130. spellId_tremove(trigger.spellIds, 2);
  4131. end
  4132. else
  4133. if(tonumber(v)) then
  4134. WeakAuras.ShowSpellIDDialog(trigger, v);
  4135. end
  4136. trigger.names[2], trigger.spellIds[2] = WeakAuras.CorrectAuraName(v);
  4137. end
  4138. WeakAuras.Add(data);
  4139. WeakAuras.SetThumbnail(data);
  4140. WeakAuras.SetIconNames(data);
  4141. WeakAuras.UpdateDisplayButton(data);
  4142. end,
  4143. },
  4144. name3space = {
  4145. type = "execute",
  4146. name = "",
  4147. width = "half",
  4148. image = function() return "", 0, 0 end,
  4149. order = 16,
  4150. hidden = function() return not (trigger.type == "aura" and trigger.names[2] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4151. },
  4152. name3icon = {
  4153. type = "execute",
  4154. name = function() return getAuraMatchesLabel(trigger.names[3]) end,
  4155. desc = function() return getAuraMatchesList(trigger.names[3]) end,
  4156. width = "half",
  4157. image = function() return iconCache[trigger.names[3]] or "", 18, 18 end,
  4158. order = 17,
  4159. disabled = function() return not iconCache[trigger.names[3]] end,
  4160. hidden = function() return not (trigger.type == "aura" and trigger.names[2] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4161. },
  4162. name3 = {
  4163. type = "input",
  4164. order = 18,
  4165. name = "",
  4166. hidden = function() return not (trigger.type == "aura" and trigger.names[2] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4167. get = function(info) return trigger.spellIds[3] and tostring(trigger.spellIds[3]) or trigger.names[3] end,
  4168. set = function(info, v)
  4169. if(v == "") then
  4170. if(trigger.names[3]) then
  4171. tremove(trigger.names, 3);
  4172. spellId_tremove(trigger.spellIds, 3);
  4173. end
  4174. else
  4175. if(tonumber(v)) then
  4176. WeakAuras.ShowSpellIDDialog(trigger, v);
  4177. end
  4178. trigger.names[3], trigger.spellIds[3] = WeakAuras.CorrectAuraName(v);
  4179. end
  4180. WeakAuras.Add(data);
  4181. WeakAuras.SetThumbnail(data);
  4182. WeakAuras.SetIconNames(data);
  4183. WeakAuras.UpdateDisplayButton(data);
  4184. end,
  4185. },
  4186. name4space = {
  4187. type = "execute",
  4188. name = "",
  4189. width = "half",
  4190. image = function() return "", 0, 0 end,
  4191. order = 19,
  4192. hidden = function() return not (trigger.type == "aura" and trigger.names[3] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4193. },
  4194. name4icon = {
  4195. type = "execute",
  4196. name = function() return getAuraMatchesLabel(trigger.names[4]) end,
  4197. desc = function() return getAuraMatchesList(trigger.names[4]) end,
  4198. width = "half",
  4199. image = function() return iconCache[trigger.names[4]] or "", 18, 18 end,
  4200. order = 20,
  4201. disabled = function() return not iconCache[trigger.names[4]] end,
  4202. hidden = function() return not (trigger.type == "aura" and trigger.names[3] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4203. },
  4204. name4 = {
  4205. type = "input",
  4206. order = 21,
  4207. name = "",
  4208. hidden = function() return not (trigger.type == "aura" and trigger.names[3] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4209. get = function(info) return trigger.spellIds[4] and tostring(trigger.spellIds[4]) or trigger.names[4] end,
  4210. set = function(info, v)
  4211. if(v == "") then
  4212. if(trigger.names[4]) then
  4213. tremove(trigger.names, 4);
  4214. spellId_tremove(trigger.spellIds, 4);
  4215. end
  4216. else
  4217. if(tonumber(v)) then
  4218. WeakAuras.ShowSpellIDDialog(trigger, v);
  4219. end
  4220. trigger.names[4], trigger.spellIds[4] = WeakAuras.CorrectAuraName(v);
  4221. end
  4222. WeakAuras.Add(data);
  4223. WeakAuras.SetThumbnail(data);
  4224. WeakAuras.SetIconNames(data);
  4225. WeakAuras.UpdateDisplayButton(data);
  4226. end,
  4227. },
  4228. name5space = {
  4229. type = "execute",
  4230. name = "",
  4231. width = "half",
  4232. image = function() return "", 0, 0 end,
  4233. order = 22,
  4234. disabled = function() return not iconCache[trigger.names[5]] end,
  4235. hidden = function() return not (trigger.type == "aura" and trigger.names[4] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4236. },
  4237. name5icon = {
  4238. type = "execute",
  4239. name = function() return getAuraMatchesLabel(trigger.names[5]) end,
  4240. desc = function() return getAuraMatchesList(trigger.names[5]) end,
  4241. width = "half",
  4242. image = function() return iconCache[trigger.names[5]] or "", 18, 18 end,
  4243. order = 23,
  4244. hidden = function() return not (trigger.type == "aura" and trigger.names[4] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4245. },
  4246. name5 = {
  4247. type = "input",
  4248. order = 24,
  4249. name = "",
  4250. hidden = function() return not (trigger.type == "aura" and trigger.names[4] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4251. get = function(info) return trigger.spellIds[5] and tostring(trigger.spellIds[5]) or trigger.names[5] end,
  4252. set = function(info, v)
  4253. if(v == "") then
  4254. if(trigger.names[5]) then
  4255. tremove(trigger.names, 5);
  4256. spellId_tremove(trigger.spellIds, 5);
  4257. end
  4258. else
  4259. if(tonumber(v)) then
  4260. WeakAuras.ShowSpellIDDialog(trigger, v);
  4261. end
  4262. trigger.names[5], trigger.spellIds[5] = WeakAuras.CorrectAuraName(v);
  4263. end
  4264. WeakAuras.Add(data);
  4265. WeakAuras.SetThumbnail(data);
  4266. WeakAuras.SetIconNames(data);
  4267. WeakAuras.UpdateDisplayButton(data);
  4268. end,
  4269. },
  4270. name6space = {
  4271. type = "execute",
  4272. name = "",
  4273. width = "half",
  4274. image = function() return "", 0, 0 end,
  4275. order = 25,
  4276. hidden = function() return not (trigger.type == "aura" and trigger.names[5] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4277. },
  4278. name6icon = {
  4279. type = "execute",
  4280. name = function() return getAuraMatchesLabel(trigger.names[6]) end,
  4281. desc = function() return getAuraMatchesList(trigger.names[6]) end,
  4282. width = "half",
  4283. image = function() return iconCache[trigger.names[6]] or "", 18, 18 end,
  4284. order = 26,
  4285. disabled = function() return not iconCache[trigger.names[6]] end,
  4286. hidden = function() return not (trigger.type == "aura" and trigger.names[5] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4287. },
  4288. name6 = {
  4289. type = "input",
  4290. order = 27,
  4291. name = "",
  4292. hidden = function() return not (trigger.type == "aura" and trigger.names[5] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4293. get = function(info) return trigger.spellIds[6] and tostring(trigger.spellIds[6]) or trigger.names[6] end,
  4294. set = function(info, v)
  4295. if(v == "") then
  4296. if(trigger.names[6]) then
  4297. tremove(trigger.names, 6);
  4298. spellId_tremove(trigger.spellIds, 6);
  4299. end
  4300. else
  4301. if(tonumber(v)) then
  4302. WeakAuras.ShowSpellIDDialog(trigger, v);
  4303. end
  4304. trigger.names[6], trigger.spellIds[6] = WeakAuras.CorrectAuraName(v);
  4305. end
  4306. WeakAuras.Add(data);
  4307. WeakAuras.SetThumbnail(data);
  4308. WeakAuras.SetIconNames(data);
  4309. WeakAuras.UpdateDisplayButton(data);
  4310. end,
  4311. },
  4312. name7space = {
  4313. type = "execute",
  4314. name = "",
  4315. width = "half",
  4316. image = function() return "", 0, 0 end,
  4317. order = 28,
  4318. hidden = function() return not (trigger.type == "aura" and trigger.names[6] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4319. },
  4320. name7icon = {
  4321. type = "execute",
  4322. name = function() return getAuraMatchesLabel(trigger.names[7]) end,
  4323. desc = function() return getAuraMatchesList(trigger.names[7]) end,
  4324. width = "half",
  4325. image = function() return iconCache[trigger.names[7]] or "", 18, 18 end,
  4326. order = 29,
  4327. disabled = function() return not iconCache[trigger.names[7]] end,
  4328. hidden = function() return not (trigger.type == "aura" and trigger.names[6] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4329. },
  4330. name7 = {
  4331. type = "input",
  4332. order = 30,
  4333. name = "",
  4334. hidden = function() return not (trigger.type == "aura" and trigger.names[6] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4335. get = function(info) return trigger.spellIds[7] and tostring(trigger.spellIds[7]) or trigger.names[7] end,
  4336. set = function(info, v)
  4337. if(v == "") then
  4338. if(trigger.names[7]) then
  4339. tremove(trigger.names, 7);
  4340. spellId_tremove(trigger.spellIds, 7);
  4341. end
  4342. else
  4343. if(tonumber(v)) then
  4344. WeakAuras.ShowSpellIDDialog(trigger, v);
  4345. end
  4346. trigger.names[7], trigger.spellIds[7] = WeakAuras.CorrectAuraName(v);
  4347. end
  4348. WeakAuras.Add(data);
  4349. WeakAuras.SetThumbnail(data);
  4350. WeakAuras.SetIconNames(data);
  4351. WeakAuras.UpdateDisplayButton(data);
  4352. end,
  4353. },
  4354. name8space = {
  4355. type = "execute",
  4356. name = "",
  4357. width = "half",
  4358. image = function() return "", 0, 0 end,
  4359. order = 31,
  4360. hidden = function() return not (trigger.type == "aura" and trigger.names[7] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4361. },
  4362. name8icon = {
  4363. type = "execute",
  4364. name = function() return getAuraMatchesLabel(trigger.names[8]) end,
  4365. desc = function() return getAuraMatchesList(trigger.names[8]) end,
  4366. width = "half",
  4367. image = function() return iconCache[trigger.names[8]] or "", 18, 18 end,
  4368. order = 32,
  4369. disabled = function() return not iconCache[trigger.names[8]] end,
  4370. hidden = function() return not (trigger.type == "aura" and trigger.names[7] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4371. },
  4372. name8 = {
  4373. type = "input",
  4374. order = 33,
  4375. name = "",
  4376. hidden = function() return not (trigger.type == "aura" and trigger.names[7] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4377. get = function(info) return trigger.spellIds[8] and tostring(trigger.spellIds[8]) or trigger.names[8] end,
  4378. set = function(info, v)
  4379. if(v == "") then
  4380. if(trigger.names[8]) then
  4381. tremove(trigger.names, 8);
  4382. spellId_tremove(trigger.spellIds, 8);
  4383. end
  4384. else
  4385. if(tonumber(v)) then
  4386. WeakAuras.ShowSpellIDDialog(trigger, v);
  4387. end
  4388. trigger.names[8], trigger.spellIds[8] = WeakAuras.CorrectAuraName(v);
  4389. end
  4390. WeakAuras.Add(data);
  4391. WeakAuras.SetThumbnail(data);
  4392. WeakAuras.SetIconNames(data);
  4393. WeakAuras.UpdateDisplayButton(data);
  4394. end,
  4395. },
  4396. name9space = {
  4397. type = "execute",
  4398. name = "",
  4399. width = "half",
  4400. image = function() return "", 0, 0 end,
  4401. order = 34,
  4402. hidden = function() return not (trigger.type == "aura" and trigger.names[8] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4403. },
  4404. name9icon = {
  4405. type = "execute",
  4406. name = function() return getAuraMatchesLabel(trigger.names[9]) end,
  4407. desc = function() return getAuraMatchesList(trigger.names[9]) end,
  4408. width = "half",
  4409. image = function() return iconCache[trigger.names[9]] or "", 18, 18 end,
  4410. order = 35,
  4411. disabled = function() return not iconCache[trigger.names[9]] end,
  4412. hidden = function() return not (trigger.type == "aura" and trigger.names[8] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4413. },
  4414. name9 = {
  4415. type = "input",
  4416. order = 36,
  4417. name = "",
  4418. hidden = function() return not (trigger.type == "aura" and trigger.names[8] and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4419. get = function(info) return trigger.spellIds[9] and tostring(trigger.spellIds[9]) or trigger.names[9] end,
  4420. set = function(info, v)
  4421. if(v == "") then
  4422. if(trigger.names[9]) then
  4423. tremove(trigger.names, 9);
  4424. spellId_tremove(trigger.spellIds, 9);
  4425. end
  4426. else
  4427. if(tonumber(v)) then
  4428. WeakAuras.ShowSpellIDDialog(trigger, v);
  4429. end
  4430. trigger.names[9], trigger.spellIds[9] = WeakAuras.CorrectAuraName(v);
  4431. end
  4432. WeakAuras.Add(data);
  4433. WeakAuras.SetThumbnail(data);
  4434. WeakAuras.SetIconNames(data);
  4435. WeakAuras.UpdateDisplayButton(data);
  4436. end,
  4437. },
  4438. useUnit = {
  4439. type = "toggle",
  4440. name = L["Unit"],
  4441. order = 40,
  4442. disabled = true,
  4443. hidden = function() return not (trigger.type == "aura"); end,
  4444. get = function() return true end
  4445. },
  4446. unit = {
  4447. type = "select",
  4448. name = L["Unit"],
  4449. order = 41,
  4450. values = function()
  4451. if(trigger.fullscan) then
  4452. return actual_unit_types_with_specific;
  4453. else
  4454. return unit_types;
  4455. end
  4456. end,
  4457. hidden = function() return not (trigger.type == "aura"); end,
  4458. set = function(info, v)
  4459. trigger.unit = v;
  4460. if(v == "multi") then
  4461. WeakAuras.ShowCloneDialog(data);
  4462. WeakAuras.UpdateCloneConfig(data);
  4463. else
  4464. WeakAuras.HideAllClones(data.id);
  4465. end
  4466. WeakAuras.Add(data);
  4467. end,
  4468. get = function()
  4469. if(trigger.fullscan and (trigger.unit == "group" or trigger.unit == "multi")) then
  4470. trigger.unit = "player";
  4471. end
  4472. return trigger.unit;
  4473. end
  4474. },
  4475. useSpecificUnit = {
  4476. type = "toggle",
  4477. name = L["Specific Unit"],
  4478. order = 42,
  4479. disabled = true,
  4480. hidden = function() return not (trigger.type == "aura" and trigger.unit == "member") end,
  4481. get = function() return true end
  4482. },
  4483. specificUnit = {
  4484. type = "input",
  4485. name = L["Specific Unit"],
  4486. order = 43,
  4487. desc = L["Can be a name or a UID (e.g., party1). Only works on friendly players in your group."],
  4488. hidden = function() return not (trigger.type == "aura" and trigger.unit == "member") end
  4489. },
  4490. useGroup_count = {
  4491. type = "toggle",
  4492. name = L["Group Member Count"],
  4493. disabled = true,
  4494. hidden = function() return not (trigger.type == "aura" and trigger.unit == "group"); end,
  4495. get = function() return true; end,
  4496. order = 45
  4497. },
  4498. group_countOperator = {
  4499. type = "select",
  4500. name = L["Operator"],
  4501. order = 46,
  4502. width = "half",
  4503. values = operator_types,
  4504. hidden = function() return not (trigger.type == "aura" and trigger.unit == "group"); end,
  4505. get = function() return trigger.group_countOperator; end
  4506. },
  4507. group_count = {
  4508. type = "input",
  4509. name = L["Count"],
  4510. desc = function()
  4511. local groupType = unit_types[trigger.unit or "group"] or "|cFFFF0000error|r";
  4512. return L["Group aura count description"]:format(groupType, groupType, groupType, groupType, groupType, groupType, groupType);
  4513. end,
  4514. order = 47,
  4515. width = "half",
  4516. hidden = function() return not (trigger.type == "aura" and trigger.unit == "group"); end,
  4517. get = function() return trigger.group_count; end,
  4518. set = function(info, v)
  4519. if(WeakAuras.ParseNumber(v)) then
  4520. trigger.group_count = v;
  4521. else
  4522. trigger.group_count = "";
  4523. end
  4524. WeakAuras.Add(data);
  4525. WeakAuras.SetThumbnail(data);
  4526. WeakAuras.SetIconNames(data);
  4527. WeakAuras.UpdateDisplayButton(data);
  4528. end
  4529. },
  4530. groupclone = {
  4531. type = "toggle",
  4532. name = L["Show all matches (Auto-clone)"],
  4533. width = "double",
  4534. hidden = function() return not (trigger.type == "aura" and trigger.unit == "group"); end,
  4535. set = function(info, v)
  4536. trigger.groupclone = v;
  4537. if(v == true) then
  4538. WeakAuras.ShowCloneDialog(data);
  4539. WeakAuras.UpdateCloneConfig(data);
  4540. else
  4541. WeakAuras.HideAllClones(data.id);
  4542. end
  4543. WeakAuras.Add(data);
  4544. end,
  4545. order = 47.1
  4546. },
  4547. name_info = {
  4548. type = "select",
  4549. name = L["Name Info"],
  4550. order = 47.3,
  4551. hidden = function() return not (trigger.type == "aura" and trigger.unit == "group" and not trigger.groupclone); end,
  4552. disabled = function() return not WeakAuras.CanShowNameInfo(data); end,
  4553. get = function()
  4554. if(WeakAuras.CanShowNameInfo(data)) then
  4555. return trigger.name_info;
  4556. else
  4557. return nil;
  4558. end
  4559. end,
  4560. values = group_aura_name_info_types
  4561. },
  4562. stack_info = {
  4563. type = "select",
  4564. name = L["Stack Info"],
  4565. order = 47.6,
  4566. hidden = function() return not (trigger.type == "aura" and trigger.unit == "group" and not trigger.groupclone); end,
  4567. disabled = function() return not WeakAuras.CanShowStackInfo(data); end,
  4568. get = function()
  4569. if(WeakAuras.CanShowStackInfo(data)) then
  4570. return trigger.stack_info;
  4571. else
  4572. return nil;
  4573. end
  4574. end,
  4575. values = group_aura_stack_info_types
  4576. },
  4577. hideAlone = {
  4578. type = "toggle",
  4579. name = L["Hide When Not In Group"],
  4580. order = 48,
  4581. width = "double",
  4582. hidden = function() return not (trigger.type == "aura" and trigger.unit == "group"); end,
  4583. },
  4584. useDebuffType = {
  4585. type = "toggle",
  4586. name = L["Aura Type"],
  4587. order = 50,
  4588. disabled = true,
  4589. hidden = function() return not (trigger.type == "aura"); end,
  4590. get = function() return true end
  4591. },
  4592. debuffType = {
  4593. type = "select",
  4594. name = L["Aura Type"],
  4595. order = 51,
  4596. values = debuff_types,
  4597. hidden = function() return not (trigger.type == "aura"); end
  4598. },
  4599. subcount = {
  4600. type = "toggle",
  4601. width = "double",
  4602. name = L["Use tooltip \"size\" instead of stacks"],
  4603. hidden = function() return not (trigger.type == "aura" and trigger.fullscan) end,
  4604. order = 55
  4605. },
  4606. useRem = {
  4607. type = "toggle",
  4608. name = L["Remaining Time"],
  4609. hidden = function() return not (trigger.type == "aura" and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4610. order = 56
  4611. },
  4612. remOperator = {
  4613. type = "select",
  4614. name = L["Operator"],
  4615. order = 57,
  4616. width = "half",
  4617. values = operator_types,
  4618. disabled = function() return not trigger.useRem; end,
  4619. hidden = function() return not (trigger.type == "aura" and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4620. get = function() return trigger.useRem and trigger.remOperator or nil end
  4621. },
  4622. rem = {
  4623. type = "input",
  4624. name = L["Remaining Time"],
  4625. validate = ValidateNumeric,
  4626. order = 58,
  4627. width = "half",
  4628. disabled = function() return not trigger.useRem; end,
  4629. hidden = function() return not (trigger.type == "aura" and not trigger.fullscan and trigger.unit ~= "multi"); end,
  4630. get = function() return trigger.useRem and trigger.rem or nil end
  4631. },
  4632. useCount = {
  4633. type = "toggle",
  4634. name = L["Stack Count"],
  4635. hidden = function() return not (trigger.type == "aura" and trigger.unit ~= "multi"); end,
  4636. order = 60
  4637. },
  4638. countOperator = {
  4639. type = "select",
  4640. name = L["Operator"],
  4641. order = 62,
  4642. width = "half",
  4643. values = operator_types,
  4644. disabled = function() return not trigger.useCount; end,
  4645. hidden = function() return not (trigger.type == "aura" and trigger.unit ~= "multi"); end,
  4646. get = function() return trigger.useCount and trigger.countOperator or nil end
  4647. },
  4648. count = {
  4649. type = "input",
  4650. name = L["Stack Count"],
  4651. validate = ValidateNumeric,
  4652. order = 65,
  4653. width = "half",
  4654. disabled = function() return not trigger.useCount; end,
  4655. hidden = function() return not (trigger.type == "aura" and trigger.unit ~= "multi"); end,
  4656. get = function() return trigger.useCount and trigger.count or nil end
  4657. },
  4658. ownOnly = {
  4659. type = "toggle",
  4660. name = function()
  4661. local value = trigger.ownOnly;
  4662. if(value == nil) then return L["Own Only"];
  4663. elseif(value == false) then return "|cFFFF0000 "..L["Negator"].." "..L["Own Only"];
  4664. else return "|cFF00FF00"..L["Own Only"]; end
  4665. end,
  4666. desc = function()
  4667. local value = trigger.ownOnly;
  4668. if(value == nil) then return L["Only match auras cast by the player"];
  4669. elseif(value == false) then return L["Only match auras cast by people other than the player"];
  4670. else return L["Only match auras cast by the player"]; end
  4671. end,
  4672. get = function()
  4673. local value = trigger.ownOnly;
  4674. if(value == nil) then return false;
  4675. elseif(value == false) then return "false";
  4676. else return "true"; end
  4677. end,
  4678. set = function(info, v)
  4679. if(v) then
  4680. trigger.ownOnly = true;
  4681. else
  4682. local value = trigger.ownOnly;
  4683. if(value == false) then trigger.ownOnly = nil;
  4684. else trigger.ownOnly = false end
  4685. end
  4686. WeakAuras.Add(data);
  4687. end,
  4688. order = 70,
  4689. hidden = function() return not (trigger.type == "aura"); end
  4690. },
  4691. inverse = {
  4692. type = "toggle",
  4693. name = L["Inverse"],
  4694. desc = function()
  4695. if(trigger.unit == "group") then
  4696. return L["Show players that are |cFFFF0000not affected"];
  4697. else
  4698. return L["Activate when the given aura(s) |cFFFF0000can't|r be found"];
  4699. end
  4700. end,
  4701. order = 75,
  4702. hidden = function() return not (trigger.type == "aura" and not(trigger.unit ~= "group" and trigger.autoclone) and trigger.unit ~= "multi" and not(trigger.unit == "group" and not trigger.groupclone)); end
  4703. }
  4704. };
  4705.  
  4706. local trigger_options = {
  4707. disjunctive = {
  4708. type = "select",
  4709. name = L["Required For Activation"],
  4710. width = "double",
  4711. order = 0,
  4712. hidden = function() return not (data.additional_triggers and #data.additional_triggers > 0) end,
  4713. values = WeakAuras.trigger_require_types,
  4714. get = function() return data.disjunctive and "any" or "all" end,
  4715. set = function(info, v) data.disjunctive = (v == "any") end
  4716. },
  4717. addTrigger = {
  4718. type = "execute",
  4719. name = L["Add Trigger"],
  4720. order = 0.5,
  4721. func = function()
  4722. if(data.controlledChildren) then
  4723. for index, childId in pairs(data.controlledChildren) do
  4724. local childData = WeakAuras.GetData(childId);
  4725. if(childData) then
  4726. childData.additional_triggers = childData.additional_triggers or {};
  4727. tinsert(childData.additional_triggers, {trigger = {}, untrigger = {}});
  4728. childData.numTriggers = 1 + (childData.additional_triggers and #childData.additional_triggers or 0)
  4729. optionTriggerChoices[childId] = #childData.additional_triggers;
  4730. WeakAuras.ReloadTriggerOptions(childData);
  4731. end
  4732. end
  4733. else
  4734. data.additional_triggers = data.additional_triggers or {};
  4735. tinsert(data.additional_triggers, {trigger = {}, untrigger = {}});
  4736. data.numTriggers = 1 + (data.additional_triggers and #data.additional_triggers or 0)
  4737. optionTriggerChoices[id] = #data.additional_triggers;
  4738. end
  4739. WeakAuras.ReloadTriggerOptions(data);
  4740. end
  4741. },
  4742. chooseTrigger = {
  4743. type = "select",
  4744. name = L["Choose Trigger"],
  4745. order = 1,
  4746. values = function()
  4747. local ret = {[0] = L["Trigger %d"]:format(1)};
  4748. if(data.controlledChildren) then
  4749. for index=1,(data.numTriggers or 9) do
  4750. local all, none, any = true, true, false;
  4751. for _, childId in pairs(data.controlledChildren) do
  4752. local childData = WeakAuras.GetData(childId);
  4753. if(childData) then
  4754. none = false;
  4755. if(childData.additional_triggers and childData.additional_triggers[index]) then
  4756. any = true;
  4757. else
  4758. all = false;
  4759. end
  4760. end
  4761. end
  4762. if not(none) then
  4763. if(all) then
  4764. ret[index] = L["Trigger %d"]:format(index + 1);
  4765. elseif(any) then
  4766. ret[index] = "|cFF777777"..L["Trigger %d"]:format(index + 1);
  4767. end
  4768. end
  4769. end
  4770. elseif(data.additional_triggers) then
  4771. for index, trigger in pairs(data.additional_triggers) do
  4772. ret[index] = L["Trigger %d"]:format(index + 1);
  4773. end
  4774. end
  4775. return ret;
  4776. end,
  4777. get = function() return optionTriggerChoices[id]; end,
  4778. set = function(info, v)
  4779. if(v == 0 or (data.additional_triggers and data.additional_triggers[v])) then
  4780. optionTriggerChoices[id] = v;
  4781. WeakAuras.ReloadTriggerOptions(data);
  4782. end
  4783. end
  4784. },
  4785. triggerHeader = {
  4786. type = "header",
  4787. name = function(info)
  4788. if(info == "default") then
  4789. return L["Multiple Triggers"];
  4790. else
  4791. if(optionTriggerChoices[id] == 0) then
  4792. return L["Trigger %d"]:format(1);
  4793. else
  4794. return L["Trigger %d"]:format(optionTriggerChoices[id] + 1);
  4795. end
  4796. end
  4797. end,
  4798. order = 2
  4799. },
  4800. deleteTrigger = {
  4801. type = "execute",
  4802. name = L["Delete Trigger"],
  4803. order = 3,
  4804. width = "double",
  4805. func = function()
  4806. if(data.controlledChildren) then
  4807. for index, childId in pairs(data.controlledChildren) do
  4808. local childData = WeakAuras.GetData(childId);
  4809. if(childData) then
  4810. tremove(childData.additional_triggers, optionTriggerChoices[childId]);
  4811. childData.numTriggers = 1 + (childData.additional_triggers and #childData.additional_triggers or 0)
  4812. optionTriggerChoices[childId] = optionTriggerChoices[childId] - 1;
  4813. WeakAuras.ReloadTriggerOptions(childData);
  4814. end
  4815. end
  4816. else
  4817. tremove(data.additional_triggers, optionTriggerChoices[id]);
  4818. data.numTriggers = 1 + (data.additional_triggers and #data.additional_triggers + 0)
  4819. optionTriggerChoices[id] = optionTriggerChoices[id] - 1;
  4820. end
  4821. WeakAuras.Add(data);
  4822. WeakAuras.ReloadTriggerOptions(data);
  4823. end,
  4824. hidden = function() return optionTriggerChoices[id] == 0; end
  4825. },
  4826. typedesc = {
  4827. type = "toggle",
  4828. name = L["Type"],
  4829. order = 5,
  4830. disabled = true,
  4831. get = function() return true end
  4832. },
  4833. type = {
  4834. type = "select",
  4835. name = L["Type"],
  4836. desc = L["The type of trigger"],
  4837. order = 6,
  4838. values = trigger_types,
  4839. set = function(info, v)
  4840. trigger.type = v;
  4841. if(trigger.event) then
  4842. local prototype = WeakAuras.event_prototypes[trigger.event];
  4843. if(prototype) then
  4844. if(v == "status" and prototype.type == "event") then
  4845. trigger.event = "Health";
  4846. elseif(v == "event" and prototype.type == "status") then
  4847. trigger.event = "Chat Message";
  4848. end
  4849. end
  4850. end
  4851. WeakAuras.Add(data);
  4852. WeakAuras.SetThumbnail(data);
  4853. WeakAuras.SetIconNames(data);
  4854. WeakAuras.UpdateDisplayButton(data);
  4855. WeakAuras.ReloadTriggerOptions(data);
  4856. end
  4857. },
  4858. event = {
  4859. type = "select",
  4860. name = function()
  4861. if(trigger.type == "event") then
  4862. return L["Event"];
  4863. elseif(trigger.type == "status") then
  4864. return L["Status"];
  4865. end
  4866. end,
  4867. order = 7,
  4868. width = "double",
  4869. values = function()
  4870. if(trigger.type == "event") then
  4871. return event_types;
  4872. elseif(trigger.type == "status") then
  4873. return status_types;
  4874. end
  4875. end,
  4876. hidden = function() return not (trigger.type == "event" or trigger.type == "status"); end
  4877. },
  4878. subeventPrefix = {
  4879. type = "select",
  4880. name = L["Message Prefix"],
  4881. order = 8,
  4882. values = subevent_prefix_types,
  4883. hidden = function() return not (trigger.type == "event" and trigger.event == "Combat Log"); end
  4884. },
  4885. subeventSuffix = {
  4886. type = "select",
  4887. name = L["Message Suffix"],
  4888. order = 9,
  4889. values = subevent_suffix_types,
  4890. hidden = function() return not (trigger.type == "event" and trigger.event == "Combat Log" and subevent_actual_prefix_types[trigger.subeventPrefix]); end
  4891. },
  4892. custom_type = {
  4893. type = "select",
  4894. name = L["Event Type"],
  4895. order = 7,
  4896. width = "double",
  4897. values = custom_trigger_types,
  4898. hidden = function() return not (trigger.type == "custom") end
  4899. },
  4900. check = {
  4901. type = "select",
  4902. name = L["Check On..."],
  4903. order = 8,
  4904. values = check_types,
  4905. hidden = function() return not (trigger.type == "custom" and trigger.custom_type == "status" and trigger.check ~= "update") end,
  4906. get = function() return trigger.check end,
  4907. set = function(info, v)
  4908. trigger.check = v;
  4909. WeakAuras.Add(data);
  4910. WeakAuras.SetThumbnail(data);
  4911. WeakAuras.SetIconNames(data);
  4912. WeakAuras.UpdateDisplayButton(data);
  4913. end
  4914. },
  4915. check2 = {
  4916. type = "select",
  4917. name = L["Check On..."],
  4918. order = 8,
  4919. width = "double",
  4920. values = check_types,
  4921. hidden = function() return not (trigger.type == "custom" and trigger.custom_type == "status" and trigger.check == "update") end,
  4922. get = function() return trigger.check end,
  4923. set = function(info, v)
  4924. trigger.check = v;
  4925. WeakAuras.Add(data);
  4926. WeakAuras.SetThumbnail(data);
  4927. WeakAuras.SetIconNames(data);
  4928. WeakAuras.UpdateDisplayButton(data);
  4929. end
  4930. },
  4931. events = {
  4932. type = "input",
  4933. name = L["Event(s)"],
  4934. desc = L["Custom trigger status tooltip"],
  4935. order = 9,
  4936. hidden = function() return not (trigger.type == "custom" and trigger.custom_type == "status" and trigger.check ~= "update") end,
  4937. get = function() return trigger.events end,
  4938. set = function(info, v)
  4939. trigger.events = v;
  4940. WeakAuras.Add(data);
  4941. WeakAuras.SetThumbnail(data);
  4942. WeakAuras.SetIconNames(data);
  4943. WeakAuras.UpdateDisplayButton(data);
  4944. end
  4945. },
  4946. events2 = {
  4947. type = "input",
  4948. name = L["Event(s)"],
  4949. desc = L["Custom trigger event tooltip"],
  4950. width = "double",
  4951. order = 9,
  4952. hidden = function() return not (trigger.type == "custom" and trigger.custom_type == "event" and trigger.check ~= "update") end,
  4953. get = function() return trigger.events end,
  4954. set = function(info, v)
  4955. trigger.events = v;
  4956. WeakAuras.Add(data);
  4957. WeakAuras.SetThumbnail(data);
  4958. WeakAuras.SetIconNames(data);
  4959. WeakAuras.UpdateDisplayButton(data);
  4960. end
  4961. },
  4962. custom_trigger = {
  4963. type = "input",
  4964. name = L["Custom Trigger"],
  4965. order = 10,
  4966. multiline = true,
  4967. width = "normal",
  4968. hidden = function() return not (trigger.type == "custom") end,
  4969. get = function() return trigger.custom end,
  4970. set = function(info, v)
  4971. trigger.custom = v;
  4972. WeakAuras.Add(data);
  4973. WeakAuras.SetThumbnail(data);
  4974. WeakAuras.SetIconNames(data);
  4975. WeakAuras.UpdateDisplayButton(data);
  4976. end
  4977. },
  4978. custom_trigger_expand = {
  4979. type = "execute",
  4980. order = 10.5,
  4981. name = L["Expand Text Editor"],
  4982. func = function()
  4983. WeakAuras.TextEditor(data, appendToTriggerPath("custom"))
  4984. end,
  4985. hidden = function() return not (trigger.type == "custom") end,
  4986. },
  4987. custom_trigger_error = {
  4988. type = "description",
  4989. name = function()
  4990. if not(trigger.custom) then
  4991. return "";
  4992. end
  4993. local _, errorString = loadstring("return "..trigger.custom);
  4994. return errorString and "|cFFFF0000"..errorString or "";
  4995. end,
  4996. width = "double",
  4997. order = 11,
  4998. hidden = function()
  4999. if not(trigger.type == "custom" and trigger.custom) then
  5000. return true;
  5001. else
  5002. local loadedFunction, errorString = loadstring("return "..trigger.custom);
  5003. if(errorString and not loadedFunction) then
  5004. return false;
  5005. else
  5006. return true;
  5007. end
  5008. end
  5009. end
  5010. },
  5011. custom_hide = {
  5012. type = "select",
  5013. name = L["Hide"],
  5014. order = 12,
  5015. hidden = function() return not (trigger.type == "custom" and trigger.custom_type == "event" and trigger.custom_hide ~= "custom") end,
  5016. values = eventend_types,
  5017. get = function() trigger.custom_hide = trigger.custom_hide or "timed"; return trigger.custom_hide end,
  5018. set = function(info, v)
  5019. trigger.custom_hide = v;
  5020. WeakAuras.Add(data);
  5021. WeakAuras.SetThumbnail(data);
  5022. WeakAuras.SetIconNames(data);
  5023. WeakAuras.UpdateDisplayButton(data);
  5024. end
  5025. },
  5026. custom_hide2 = {
  5027. type = "select",
  5028. name = L["Hide"],
  5029. order = 12,
  5030. width = "double",
  5031. hidden = function() return not (trigger.type == "custom" and trigger.custom_type == "event" and trigger.custom_hide == "custom") end,
  5032. values = eventend_types,
  5033. get = function() return trigger.custom_hide end,
  5034. set = function(info, v)
  5035. trigger.custom_hide = v;
  5036. WeakAuras.Add(data);
  5037. WeakAuras.SetThumbnail(data);
  5038. WeakAuras.SetIconNames(data);
  5039. WeakAuras.UpdateDisplayButton(data);
  5040. end
  5041. },
  5042. duration = {
  5043. type = "input",
  5044. name = L["Duration (s)"],
  5045. order = 13,
  5046. hidden = function() return not (trigger.type == "custom" and trigger.custom_type == "event" and trigger.custom_hide ~= "custom") end
  5047. },
  5048. custom_untrigger = {
  5049. type = "input",
  5050. name = L["Custom Untrigger"],
  5051. order = 14,
  5052. multiline = true,
  5053. width = "normal",
  5054. hidden = function() return not (trigger.type == "custom" and (trigger.custom_type == "status" or trigger.custom_hide == "custom")) end,
  5055. get = function() return untrigger and untrigger.custom end,
  5056. set = function(info, v)
  5057. if(untrigger) then
  5058. untrigger.custom = v;
  5059. end
  5060. WeakAuras.Add(data);
  5061. WeakAuras.SetThumbnail(data);
  5062. WeakAuras.SetIconNames(data);
  5063. WeakAuras.UpdateDisplayButton(data);
  5064. end
  5065. },
  5066. custom_untrigger_expand = {
  5067. type = "execute",
  5068. order = 14.5,
  5069. name = L["Expand Text Editor"],
  5070. func = function()
  5071. WeakAuras.TextEditor(data, appendToUntriggerPath("custom"))
  5072. end,
  5073. hidden = function() return not (trigger.type == "custom" and (trigger.custom_type == "status" or trigger.custom_hide == "custom")) end,
  5074. },
  5075. custom_untrigger_error = {
  5076. type = "description",
  5077. name = function()
  5078. if not(untrigger and untrigger.custom) then
  5079. return "";
  5080. end
  5081. local _, errorString = loadstring("return "..(untrigger and untrigger.custom or ""));
  5082. return errorString and "|cFFFF0000"..errorString or "";
  5083. end,
  5084. width = "double",
  5085. order = 15,
  5086. hidden = function()
  5087. if not(trigger.type == "custom" and (trigger.custom_type == "status" or trigger.custom_hide == "custom") and untrigger and untrigger.custom) then
  5088. return true;
  5089. else
  5090. local loadedFunction, errorString = loadstring("return "..(untrigger and untrigger.custom or ""));
  5091. if(errorString and not loadedFunction) then
  5092. return false;
  5093. else
  5094. return true;
  5095. end
  5096. end
  5097. end
  5098. },
  5099. custom_duration = {
  5100. type = "input",
  5101. name = L["Duration Info"],
  5102. order = 16,
  5103. multiline = true,
  5104. width = "normal",
  5105. hidden = function() return not (trigger.type == "custom" and (trigger.custom_type == "status" or trigger.custom_hide ~= "timed")) end,
  5106. get = function() return trigger.customDuration end,
  5107. set = function(info, v)
  5108. trigger.customDuration = v;
  5109. WeakAuras.Add(data);
  5110. WeakAuras.SetThumbnail(data);
  5111. WeakAuras.SetIconNames(data);
  5112. WeakAuras.UpdateDisplayButton(data);
  5113. end
  5114. },
  5115. custom_duration_expand = {
  5116. type = "execute",
  5117. order = 16.5,
  5118. name = L["Expand Text Editor"],
  5119. func = function()
  5120. WeakAuras.TextEditor(data, appendToTriggerPath("customDuration"))
  5121. end,
  5122. hidden = function() return not (trigger.type == "custom" and (trigger.custom_type == "status" or trigger.custom_hide ~= "timed")) end,
  5123. },
  5124. custom_duration_error = {
  5125. type = "description",
  5126. name = function()
  5127. if not(trigger.type == "custom" and (trigger.custom_type == "status" or trigger.custom_hide ~= "timed") and trigger.customDuration and trigger.customDuration ~= "") then
  5128. return "";
  5129. end
  5130. local _, errorString = loadstring("return "..(trigger.customDuration or ""));
  5131. return errorString and "|cFFFF0000"..errorString or "";
  5132. end,
  5133. width = "double",
  5134. order = 17,
  5135. hidden = function()
  5136. if not(trigger.type == "custom" and (trigger.custom_hide ~= "timed") and trigger.customDuration and trigger.customDuration ~= "") then
  5137. return true;
  5138. else
  5139. local loadedFunction, errorString = loadstring("return "..(trigger.customDuration or ""));
  5140. if(errorString and not loadedFunction) then
  5141. return false;
  5142. else
  5143. return true;
  5144. end
  5145. end
  5146. end
  5147. },
  5148. custom_name = {
  5149. type = "input",
  5150. name = L["Name Info"],
  5151. order = 18,
  5152. multiline = true,
  5153. width = "normal",
  5154. hidden = function() return not (trigger.type == "custom") end,
  5155. get = function() return trigger.customName end,
  5156. set = function(info, v)
  5157. trigger.customName = v;
  5158. WeakAuras.Add(data);
  5159. WeakAuras.SetThumbnail(data);
  5160. WeakAuras.SetIconNames(data);
  5161. WeakAuras.UpdateDisplayButton(data);
  5162. end
  5163. },
  5164. custom_name_expand = {
  5165. type = "execute",
  5166. order = 18.5,
  5167. name = L["Expand Text Editor"],
  5168. func = function()
  5169. WeakAuras.TextEditor(data, appendToTriggerPath("customName"))
  5170. end,
  5171. hidden = function() return not (trigger.type == "custom") end,
  5172. },
  5173. custom_name_error = {
  5174. type = "description",
  5175. name = function()
  5176. if not(trigger.customName and trigger.customName ~= "") then
  5177. return "";
  5178. end
  5179. local _, errorString = loadstring("return "..(trigger.customName or ""));
  5180. return errorString and "|cFFFF0000"..errorString or "";
  5181. end,
  5182. width = "double",
  5183. order = 19,
  5184. hidden = function()
  5185. if not(trigger.type == "custom" and trigger.customName and trigger.customName ~= "") then
  5186. return true;
  5187. else
  5188. local loadedFunction, errorString = loadstring("return "..(trigger.customName or ""));
  5189. if(errorString and not loadedFunction) then
  5190. return false;
  5191. else
  5192. return true;
  5193. end
  5194. end
  5195. end
  5196. },
  5197. custom_icon = {
  5198. type = "input",
  5199. name = L["Icon Info"],
  5200. order = 20,
  5201. multiline = true,
  5202. width = "normal",
  5203. hidden = function() return not (trigger.type == "custom") end,
  5204. get = function() return trigger.customIcon end,
  5205. set = function(info, v)
  5206. trigger.customIcon = v;
  5207. WeakAuras.Add(data);
  5208. WeakAuras.SetThumbnail(data);
  5209. WeakAuras.SetIconNames(data);
  5210. WeakAuras.UpdateDisplayButton(data);
  5211. end
  5212. },
  5213. custom_icon_expand = {
  5214. type = "execute",
  5215. order = 20.5,
  5216. name = L["Expand Text Editor"],
  5217. func = function()
  5218. WeakAuras.TextEditor(data, appendToTriggerPath("customIcon"))
  5219. end,
  5220. hidden = function() return not (trigger.type == "custom") end,
  5221. },
  5222. custom_icon_error = {
  5223. type = "description",
  5224. name = function()
  5225. if not(trigger.customIcon and trigger.customIcon ~= "") then
  5226. return "";
  5227. end
  5228. local _, errorString = loadstring("return "..(trigger.customIcon or ""));
  5229. return errorString and "|cFFFF0000"..errorString or "";
  5230. end,
  5231. width = "double",
  5232. order = 21,
  5233. hidden = function()
  5234. if not(trigger.type == "custom" and trigger.customIcon and trigger.customIcon ~= "") then
  5235. return true;
  5236. else
  5237. local loadedFunction, errorString = loadstring("return "..(trigger.customIcon or ""));
  5238. if(errorString and not loadedFunction) then
  5239. return false;
  5240. else
  5241. return true;
  5242. end
  5243. end
  5244. end
  5245. },
  5246. custom_texture = {
  5247. type = "input",
  5248. name = L["Texture Info"],
  5249. order = 21.5,
  5250. multiline = true,
  5251. width = "normal",
  5252. hidden = function() return not (trigger.type == "custom") end,
  5253. get = function() return trigger.customTexture end,
  5254. set = function(info, v)
  5255. trigger.customTexture = v;
  5256. WeakAuras.Add(data);
  5257. WeakAuras.SetThumbnail(data);
  5258. WeakAuras.SetIconNames(data);
  5259. WeakAuras.UpdateDisplayButton(data);
  5260. end
  5261. },
  5262. custom_texture_expand = {
  5263. type = "execute",
  5264. order = 22,
  5265. name = L["Expand Text Editor"],
  5266. func = function()
  5267. WeakAuras.TextEditor(data, appendToTriggerPath("customTexture"))
  5268. end,
  5269. hidden = function() return not (trigger.type == "custom") end,
  5270. },
  5271. custom_texture_error = {
  5272. type = "description",
  5273. name = function()
  5274. if not(trigger.customTexture and trigger.customTexture ~= "") then
  5275. return "";
  5276. end
  5277. local _, errorString = loadstring("return "..(trigger.customTexture or ""));
  5278. return errorString and "|cFFFF0000"..errorString or "";
  5279. end,
  5280. width = "double",
  5281. order = 22.5,
  5282. hidden = function()
  5283. if not(trigger.type == "custom" and trigger.customTexture and trigger.customTexture ~= "") then
  5284. return true;
  5285. else
  5286. local loadedFunction, errorString = loadstring("return "..(trigger.customTexture or ""));
  5287. if(errorString and not loadedFunction) then
  5288. return false;
  5289. else
  5290. return true;
  5291. end
  5292. end
  5293. end
  5294. },
  5295. custom_stacks = {
  5296. type = "input",
  5297. name = L["Stack Info"],
  5298. order = 23,
  5299. multiline = true,
  5300. width = "normal",
  5301. hidden = function() return not (trigger.type == "custom") end,
  5302. get = function() return trigger.customStacks end,
  5303. set = function(info, v)
  5304. trigger.customStacks = v;
  5305. WeakAuras.Add(data);
  5306. WeakAuras.SetThumbnail(data);
  5307. WeakAuras.SetIconNames(data);
  5308. WeakAuras.UpdateDisplayButton(data);
  5309. end
  5310. },
  5311. custom_stacks_expand = {
  5312. type = "execute",
  5313. order = 23.5,
  5314. name = L["Expand Text Editor"],
  5315. func = function()
  5316. WeakAuras.TextEditor(data, appendToTriggerPath("customStacks"))
  5317. end,
  5318. hidden = function() return not (trigger.type == "custom") end,
  5319. },
  5320. custom_stacks_error = {
  5321. type = "description",
  5322. name = function()
  5323. if not(trigger.customStacks and trigger.customStacks ~= "") then
  5324. return "";
  5325. end
  5326. local _, errorString = loadstring("return "..(trigger.customStacks or ""));
  5327. return errorString and "|cFFFF0000"..errorString or "";
  5328. end,
  5329. width = "double",
  5330. order = 24,
  5331. hidden = function()
  5332. if not(trigger.type == "custom" and trigger.customStacks and trigger.customStacks ~= "") then
  5333. return true;
  5334. else
  5335. local loadedFunction, errorString = loadstring("return "..(trigger.customStacks or ""));
  5336. if(errorString and not loadedFunction) then
  5337. return false;
  5338. else
  5339. return true;
  5340. end
  5341. end
  5342. end
  5343. }
  5344. };
  5345.  
  5346. local order = 81;
  5347.  
  5348. if(data.controlledChildren) then
  5349. local function options_set(info, ...)
  5350. setAll(data, info, ...);
  5351. WeakAuras.Add(data);
  5352. WeakAuras.SetThumbnail(data);
  5353. WeakAuras.SetIconNames(data);
  5354. WeakAuras.UpdateDisplayButton(data);
  5355. WeakAuras.ReloadTriggerOptions(data);
  5356. end
  5357.  
  5358. removeFuncs(displayOptions[id]);
  5359.  
  5360. if(optionTriggerChoices[id] >= 0 and getAll(data, {"trigger", "type"}) == "aura") then
  5361. displayOptions[id].args.trigger.args = union(trigger_options, aura_options);
  5362. removeFuncs(displayOptions[id].args.trigger);
  5363. displayOptions[id].args.trigger.args.type.set = options_set;
  5364. elseif(optionTriggerChoices[id] >= 0 and (getAll(data, {"trigger", "type"}) == "event" or getAll(data, {"trigger", "type"}) == "status")) then
  5365. local event = getAll(data, {"trigger", "event"});
  5366. local unevent = getAll(data, {"trigger", "unevent"});
  5367. if(event and WeakAuras.event_prototypes[event]) then
  5368. local trigger_options_created;
  5369. if(event == "Combat Log") then
  5370. local subeventPrefix = getAll(data, {"trigger", "subeventPrefix"});
  5371. local subeventSuffix = getAll(data, {"trigger", "subeventSuffix"});
  5372. if(subeventPrefix and subeventSuffix) then
  5373. trigger_options_created = true;
  5374. displayOptions[id].args.trigger.args = union(trigger_options, WeakAuras.ConstructOptions(WeakAuras.event_prototypes[event], data, 10, subeventPrefix, subeventSuffix, optionTriggerChoices[id], nil, unevent));
  5375. end
  5376. end
  5377.  
  5378. if not(trigger_options_created) then
  5379. displayOptions[id].args.trigger.args = union(trigger_options, WeakAuras.ConstructOptions(WeakAuras.event_prototypes[event], data, 10, nil, nil, optionTriggerChoices[id], nil, unevent));
  5380. end
  5381. else
  5382. displayOptions[id].args.trigger.args = union(trigger_options, {});
  5383. removeFuncs(displayOptions[id].args.trigger);
  5384. end
  5385. removeFuncs(displayOptions[id].args.trigger);
  5386. replaceNameDescFuncs(displayOptions[id].args.trigger, data);
  5387. replaceImageFuncs(displayOptions[id].args.trigger, data);
  5388.  
  5389. if(displayOptions[id].args.trigger.args.unevent) then
  5390. displayOptions[id].args.trigger.args.unevent.set = options_set;
  5391. end
  5392. if(displayOptions[id].args.trigger.args.subeventPrefix) then
  5393. displayOptions[id].args.trigger.args.subeventPrefix.set = function(info, v)
  5394. if not(subevent_actual_prefix_types[v]) then
  5395. data.trigger.subeventSuffix = "";
  5396. end
  5397. options_set(info, v);
  5398. end
  5399. end
  5400. if(displayOptions[id].args.trigger.args.subeventSuffix) then
  5401. displayOptions[id].args.trigger.args.subeventSuffix.set = options_set;
  5402. end
  5403.  
  5404. if(displayOptions[id].args.trigger.args.type) then
  5405. displayOptions[id].args.trigger.args.type.set = options_set;
  5406. end
  5407. if(displayOptions[id].args.trigger.args.event) then
  5408. displayOptions[id].args.trigger.args.event.set = options_set;
  5409. end
  5410. else
  5411. displayOptions[id].args.trigger.args = trigger_options;
  5412. removeFuncs(displayOptions[id].args.trigger);
  5413. end
  5414.  
  5415. displayOptions[id].get = function(info, ...) return getAll(data, info, ...); end;
  5416. displayOptions[id].set = function(info, ...)
  5417. setAll(data, info, ...);
  5418. if(type(id) == "string") then
  5419. WeakAuras.Add(data);
  5420. WeakAuras.SetThumbnail(data);
  5421. WeakAuras.ResetMoverSizer();
  5422. end
  5423. end
  5424. displayOptions[id].hidden = function(info, ...) return hiddenAll(data, info, ...); end;
  5425. displayOptions[id].disabled = function(info, ...) return disabledAll(data, info, ...); end;
  5426.  
  5427. trigger_options.chooseTrigger.set = options_set;
  5428. trigger_options.type.set = options_set;
  5429. trigger_options.event.set = options_set;
  5430.  
  5431. replaceNameDescFuncs(displayOptions[id], data);
  5432. replaceImageFuncs(displayOptions[id], data);
  5433.  
  5434. local regionOption = regionOptions[data.regionType].create(id, data);
  5435. displayOptions[id].args.group = {
  5436. type = "group",
  5437. name = L["Group"],
  5438. order = 0,
  5439. get = function(info)
  5440. if(info.type == "color") then
  5441. data[info[#info]] = data[info[#info]] or {};
  5442. local c = data[info[#info]];
  5443. return c[1], c[2], c[3], c[4];
  5444. else
  5445. return data[info[#info]];
  5446. end
  5447. end,
  5448. set = function(info, v, g, b, a)
  5449. if(info.type == "color") then
  5450. data[info[#info]] = data[info[#info]] or {};
  5451. local c = data[info[#info]];
  5452. c[1], c[2], c[3], c[4] = v, g, b, a;
  5453. elseif(info.type == "toggle") then
  5454. data[info[#info]] = v;
  5455. else
  5456. data[info[#info]] = (v ~= "" and v) or nil;
  5457. end
  5458. WeakAuras.Add(data);
  5459. WeakAuras.SetThumbnail(data);
  5460. WeakAuras.SetIconNames(data);
  5461. WeakAuras.ResetMoverSizer();
  5462. end,
  5463. hidden = function() return false end,
  5464. disabled = function() return false end,
  5465. args = regionOption
  5466. };
  5467.  
  5468. data.load.use_class = getAll(data, {"load", "use_class"});
  5469. local single_class = getAll(data, {"load", "class"});
  5470. data.load.class = {}
  5471. data.load.class.single = single_class;
  5472.  
  5473. displayOptions[id].args.load.args = WeakAuras.ConstructOptions(WeakAuras.load_prototype, data, 10, nil, nil, optionTriggerChoices[id], "load");
  5474. removeFuncs(displayOptions[id].args.load);
  5475. replaceNameDescFuncs(displayOptions[id].args.load, data);
  5476. replaceImageFuncs(displayOptions[id].args.load, data);
  5477.  
  5478. WeakAuras.ReloadGroupRegionOptions(data);
  5479. else
  5480. local function options_set(info, v)
  5481. trigger[info[#info]] = v;
  5482. WeakAuras.Add(data);
  5483. WeakAuras.SetThumbnail(data);
  5484. WeakAuras.SetIconNames(data);
  5485. WeakAuras.UpdateDisplayButton(data);
  5486. WeakAuras.ReloadTriggerOptions(data);
  5487. end
  5488. if(trigger.type == "aura") then
  5489. displayOptions[id].args.trigger.args = union(trigger_options, aura_options);
  5490. elseif(trigger.type == "event" or trigger.type == "status") then
  5491. if(WeakAuras.event_prototypes[trigger.event]) then
  5492. if(trigger.event == "Combat Log") then
  5493. displayOptions[id].args.trigger.args = union(trigger_options, WeakAuras.ConstructOptions(WeakAuras.event_prototypes[trigger.event], data, 10, (trigger.subeventPrefix or ""), (trigger.subeventSuffix or ""), optionTriggerChoices[id]));
  5494. else
  5495. displayOptions[id].args.trigger.args = union(trigger_options, WeakAuras.ConstructOptions(WeakAuras.event_prototypes[trigger.event], data, 10, nil, nil, optionTriggerChoices[id]));
  5496. end
  5497. if(displayOptions[id].args.trigger.args.unevent) then
  5498. displayOptions[id].args.trigger.args.unevent.set = options_set;
  5499. end
  5500. if(displayOptions[id].args.trigger.args.subeventPrefix) then
  5501. displayOptions[id].args.trigger.args.subeventPrefix.set = function(info, v)
  5502. if not(subevent_actual_prefix_types[v]) then
  5503. trigger.subeventSuffix = "";
  5504. end
  5505. options_set(info, v);
  5506. end
  5507. end
  5508. if(displayOptions[id].args.trigger.args.subeventSuffix) then
  5509. displayOptions[id].args.trigger.args.subeventSuffix.set = options_set;
  5510. end
  5511. else
  5512. print("No prototype for", trigger.event);
  5513. displayOptions[id].args.trigger.args = union(trigger_options, {});
  5514. end
  5515. else
  5516. displayOptions[id].args.trigger.args = union(trigger_options, {});
  5517. end
  5518.  
  5519. displayOptions[id].args.load.args = WeakAuras.ConstructOptions(WeakAuras.load_prototype, data, 10, nil, nil, optionTriggerChoices[id], "load");
  5520.  
  5521. trigger_options.event.set = function(info, v, ...)
  5522. local prototype = WeakAuras.event_prototypes[v];
  5523. if(prototype) then
  5524. if(prototype.automatic or prototype.automaticrequired) then
  5525. trigger.unevent = "auto";
  5526. else
  5527. trigger.unevent = "timed";
  5528. end
  5529. end
  5530. options_set(info, v, ...);
  5531. end
  5532. trigger.event = trigger.event or "Health";
  5533. trigger.subeventPrefix = trigger.subeventPrefix or "SPELL"
  5534. trigger.subeventSuffix = trigger.subeventSuffix or "_CAST_START";
  5535.  
  5536. displayOptions[id].args.trigger.get = function(info) return trigger[info[#info]] end;
  5537. displayOptions[id].args.trigger.set = function(info, v)
  5538. trigger[info[#info]] = (v ~= "" and v) or nil;
  5539. WeakAuras.Add(data);
  5540. WeakAuras.SetThumbnail(data);
  5541. WeakAuras.SetIconNames(data);
  5542. WeakAuras.UpdateDisplayButton(data);
  5543. end;
  5544. end
  5545. if(type(id) ~= "string") then
  5546. displayOptions[id].args.group = nil;
  5547. end
  5548. end
  5549.  
  5550. function WeakAuras.ReloadGroupRegionOptions(data)
  5551. local regionType;
  5552. local first = true;
  5553. for index, childId in ipairs(data.controlledChildren) do
  5554. local childData = WeakAuras.GetData(childId);
  5555. if(childData) then
  5556. if(first) then
  5557. regionType = childData.regionType;
  5558. first = false;
  5559. else
  5560. if(childData.regionType ~= regionType) then
  5561. regionType = false;
  5562. end
  5563. end
  5564. end
  5565. end
  5566.  
  5567. local id = data.id;
  5568. WeakAuras.EnsureOptions(id);
  5569. local options = displayOptions[id];
  5570. local regionOption;
  5571. if(regionType) then
  5572. if(regionOptions[regionType]) then
  5573. regionOption = regionOptions[regionType].create(id, data);
  5574. end
  5575. end
  5576. if(regionOption) then
  5577. if(data.regionType == "dynamicgroup") then
  5578. regionOption.selfPoint = nil;
  5579. regionOption.anchorPoint = nil;
  5580. regionOption.anchorPointGroup = nil;
  5581. regionOption.xOffset1 = nil;
  5582. regionOption.xOffset2 = nil;
  5583. regionOption.xOffset3 = nil;
  5584. regionOption.yOffset1 = nil;
  5585. regionOption.yOffset2 = nil;
  5586. regionOption.yOffset3 = nil;
  5587. end
  5588. replaceNameDescFuncs(regionOption, data);
  5589. replaceImageFuncs(regionOption, data);
  5590. else
  5591. regionOption = {
  5592. invalid = {
  5593. type = "description",
  5594. name = L["The children of this group have different display types, so their display options cannot be set as a group."],
  5595. fontSize = "large"
  5596. }
  5597. };
  5598. end
  5599. removeFuncs(regionOption);
  5600. options.args.region.args = regionOption;
  5601. end
  5602.  
  5603. function WeakAuras.AddPositionOptions(input, id, data)
  5604. local screenWidth, screenHeight = math.ceil(GetScreenWidth() / 20) * 20, math.ceil(GetScreenHeight() / 20) * 20;
  5605. local positionOptions = {
  5606. width = {
  5607. type = "range",
  5608. name = L["Width"],
  5609. order = 60,
  5610. min = 1,
  5611. softMax = screenWidth,
  5612. bigStep = 1
  5613. },
  5614. height = {
  5615. type = "range",
  5616. name = L["Height"],
  5617. order = 65,
  5618. min = 1,
  5619. softMax = screenHeight,
  5620. bigStep = 1
  5621. },
  5622. selfPoint = {
  5623. type = "select",
  5624. name = L["Anchor"],
  5625. order = 70,
  5626. hidden = function() return data.parent and db.displays[data.parent] and db.displays[data.parent].regionType == "dynamicgroup"; end,
  5627. values = point_types
  5628. },
  5629. anchorPoint = {
  5630. type = "select",
  5631. name = L["to screen's"],
  5632. order = 75,
  5633. hidden = function() return data.parent; end,
  5634. values = point_types
  5635. },
  5636. anchorPointGroup = {
  5637. type = "select",
  5638. name = L["to group's"],
  5639. order = 75,
  5640. hidden = function() return (not data.parent) or (db.displays[data.parent] and db.displays[data.parent].regionType == "dynamicgroup"); end,
  5641. disabled = true,
  5642. values = {["CENTER"] = L["Anchor Point"]},
  5643. get = function() return "CENTER"; end
  5644. },
  5645. xOffset1 = {
  5646. type = "range",
  5647. name = L["X Offset"],
  5648. order = 80,
  5649. softMin = 0,
  5650. softMax = screenWidth,
  5651. bigStep = 10,
  5652. hidden = function() return (data.parent and db.displays[data.parent] and db.displays[data.parent].regionType == "dynamicgroup") or not data.anchorPoint:find("LEFT") end,
  5653. get = function() return data.xOffset end,
  5654. set = function(info, v)
  5655. data.xOffset = v;
  5656. WeakAuras.Add(data);
  5657. WeakAuras.SetThumbnail(data);
  5658. WeakAuras.ResetMoverSizer();
  5659. if(data.parent) then
  5660. local parentData = WeakAuras.GetData(data.parent);
  5661. if(parentData) then
  5662. WeakAuras.Add(parentData);
  5663. WeakAuras.SetThumbnail(parentData);
  5664. end
  5665. end
  5666. end
  5667. },
  5668. xOffset2 = {
  5669. type = "range",
  5670. name = L["X Offset"],
  5671. order = 80,
  5672. softMin = ((-1/2) * screenWidth),
  5673. softMax = ((1/2) * screenWidth),
  5674. bigStep = 10,
  5675. hidden = function() return (data.parent and db.displays[data.parent] and db.displays[data.parent].regionType == "dynamicgroup") or (data.anchorPoint:find("LEFT") or data.anchorPoint:find("RIGHT")) end,
  5676. get = function() return data.xOffset end,
  5677. set = function(info, v)
  5678. data.xOffset = v;
  5679. WeakAuras.Add(data);
  5680. WeakAuras.SetThumbnail(data);
  5681. WeakAuras.ResetMoverSizer();
  5682. if(data.parent) then
  5683. local parentData = WeakAuras.GetData(data.parent);
  5684. if(parentData) then
  5685. WeakAuras.Add(parentData);
  5686. WeakAuras.SetThumbnail(parentData);
  5687. end
  5688. end
  5689. end
  5690. },
  5691. xOffset3 = {
  5692. type = "range",
  5693. name = L["X Offset"],
  5694. order = 80,
  5695. softMin = (-1 * screenWidth),
  5696. softMax = 0,
  5697. bigStep = 10,
  5698. hidden = function() return (data.parent and db.displays[data.parent] and db.displays[data.parent].regionType == "dynamicgroup") or not data.anchorPoint:find("RIGHT") end,
  5699. get = function() return data.xOffset end,
  5700. set = function(info, v)
  5701. data.xOffset = v;
  5702. WeakAuras.Add(data);
  5703. WeakAuras.SetThumbnail(data);
  5704. WeakAuras.ResetMoverSizer();
  5705. if(data.parent) then
  5706. local parentData = WeakAuras.GetData(data.parent);
  5707. if(parentData) then
  5708. WeakAuras.Add(parentData);
  5709. WeakAuras.SetThumbnail(parentData);
  5710. end
  5711. end
  5712. end
  5713. },
  5714. yOffset1 = {
  5715. type = "range",
  5716. name = L["Y Offset"],
  5717. order = 85,
  5718. softMin = 0,
  5719. softMax = screenHeight,
  5720. bigStep = 10,
  5721. hidden = function() return (data.parent and db.displays[data.parent] and db.displays[data.parent].regionType == "dynamicgroup") or not data.anchorPoint:find("BOTTOM") end,
  5722. get = function() return data.yOffset end,
  5723. set = function(info, v)
  5724. data.yOffset = v;
  5725. WeakAuras.Add(data);
  5726. WeakAuras.SetThumbnail(data);
  5727. WeakAuras.ResetMoverSizer();
  5728. if(data.parent) then
  5729. local parentData = WeakAuras.GetData(data.parent);
  5730. if(parentData) then
  5731. WeakAuras.Add(parentData);
  5732. WeakAuras.SetThumbnail(parentData);
  5733. end
  5734. end
  5735. end
  5736. },
  5737. yOffset2 = {
  5738. type = "range",
  5739. name = L["Y Offset"],
  5740. order = 85,
  5741. softMin = ((-1/2) * screenHeight),
  5742. softMax = ((1/2) * screenHeight),
  5743. bigStep = 10,
  5744. hidden = function() return (data.parent and db.displays[data.parent] and db.displays[data.parent].regionType == "dynamicgroup") or (data.anchorPoint:find("BOTTOM") or data.anchorPoint:find("TOP")) end,
  5745. get = function() return data.yOffset end,
  5746. set = function(info, v)
  5747. data.yOffset = v;
  5748. WeakAuras.Add(data);
  5749. WeakAuras.SetThumbnail(data);
  5750. WeakAuras.ResetMoverSizer();
  5751. if(data.parent) then
  5752. local parentData = WeakAuras.GetData(data.parent);
  5753. if(parentData) then
  5754. WeakAuras.Add(parentData);
  5755. WeakAuras.SetThumbnail(parentData);
  5756. end
  5757. end
  5758. end
  5759. },
  5760. yOffset3 = {
  5761. type = "range",
  5762. name = L["Y Offset"],
  5763. order = 85,
  5764. softMin = (-1 * screenHeight),
  5765. softMax = 0,
  5766. bigStep = 10,
  5767. hidden = function() return (data.parent and db.displays[data.parent] and db.displays[data.parent].regionType == "dynamicgroup") or not data.anchorPoint:find("TOP") end,
  5768. get = function() return data.yOffset end,
  5769. set = function(info, v)
  5770. data.yOffset = v;
  5771. WeakAuras.Add(data);
  5772. WeakAuras.SetThumbnail(data);
  5773. WeakAuras.ResetMoverSizer();
  5774. if(data.parent) then
  5775. local parentData = WeakAuras.GetData(data.parent);
  5776. if(parentData) then
  5777. WeakAuras.Add(parentData);
  5778. WeakAuras.SetThumbnail(parentData);
  5779. end
  5780. end
  5781. end
  5782. },
  5783. frameStrata = {
  5784. type = "select",
  5785. name = L["Frame Strata"],
  5786. order = 90,
  5787. values = WeakAuras.frame_strata_types
  5788. }
  5789. };
  5790.  
  5791. return union(input, positionOptions);
  5792. end
  5793.  
  5794. function WeakAuras.AddBorderOptions(input, id, data)
  5795. local borderOptions = {
  5796. border = {
  5797. type = "toggle",
  5798. name = L["Border"],
  5799. order = 46.05
  5800. },
  5801. borderEdge = {
  5802. type = "select",
  5803. dialogControl = "LSM30_Border",
  5804. name = L["Border Style"],
  5805. order = 46.1,
  5806. values = AceGUIWidgetLSMlists.border,
  5807. disabled = function() return not data.border end,
  5808. hidden = function() return not data.border end,
  5809. },
  5810. borderBackdrop = {
  5811. type = "select",
  5812. dialogControl = "LSM30_Background",
  5813. name = L["Backdrop Style"],
  5814. order = 46.2,
  5815. values = AceGUIWidgetLSMlists.background,
  5816. disabled = function() return not data.border end,
  5817. hidden = function() return not data.border end,
  5818. },
  5819. borderOffset = {
  5820. type = "range",
  5821. name = L["Border Offset"],
  5822. order = 46.3,
  5823. softMin = 0,
  5824. softMax = 32,
  5825. bigStep = 1,
  5826. disabled = function() return not data.border end,
  5827. hidden = function() return not data.border end,
  5828. },
  5829. borderSize = {
  5830. type = "range",
  5831. name = L["Border Size"],
  5832. order = 46.4,
  5833. softMin = 1,
  5834. softMax = 64,
  5835. bigStep = 1,
  5836. disabled = function() return not data.border end,
  5837. hidden = function() return not data.border end,
  5838. },
  5839. borderInset = {
  5840. type = "range",
  5841. name = L["Border Inset"],
  5842. order = 46.5,
  5843. softMin = 1,
  5844. softMax = 32,
  5845. bigStep = 1,
  5846. disabled = function() return not data.border end,
  5847. hidden = function() return not data.border end,
  5848. },
  5849. borderColor = {
  5850. type = "color",
  5851. name = L["Border Color"],
  5852. hasAlpha = true,
  5853. order = 46.6,
  5854. disabled = function() return not data.border end,
  5855. hidden = function() return not data.border end,
  5856. },
  5857. backdropColor = {
  5858. type = "color",
  5859. name = L["Backdrop Color"],
  5860. hasAlpha = true,
  5861. order = 46.8,
  5862. disabled = function() return not data.border end,
  5863. hidden = function() return not data.border end,
  5864. },
  5865. }
  5866.  
  5867. return union(input, borderOptions);
  5868. end
  5869.  
  5870. function WeakAuras.CreateFrame()
  5871. local WeakAuras_DropDownMenu = CreateFrame("frame", "WeakAuras_DropDownMenu", nil, "UIDropDownMenuTemplate");
  5872. local frame;
  5873. -------- Mostly Copied from AceGUIContainer-Frame--------
  5874. frame = CreateFrame("FRAME", nil, UIParent);
  5875. frame:SetBackdrop({
  5876. bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
  5877. edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
  5878. tile = true,
  5879. tileSize = 32,
  5880. edgeSize = 32,
  5881. insets = { left = 8, right = 8, top = 8, bottom = 8 }
  5882. });
  5883. frame:SetBackdropColor(0, 0, 0, 1);
  5884. frame:EnableMouse(true);
  5885. frame:SetMovable(true);
  5886. frame:SetResizable(true);
  5887. frame:SetMinResize(610, 240);
  5888. frame:SetFrameStrata("DIALOG");
  5889. frame.window = "default";
  5890.  
  5891. local xOffset, yOffset;
  5892. if(db.frame) then
  5893. xOffset, yOffset = db.frame.xOffset, db.frame.yOffset;
  5894. end
  5895. if not(xOffset and yOffset) then
  5896. xOffset = (610 - GetScreenWidth()) / 2;
  5897. yOffset = (492 - GetScreenHeight()) / 2;
  5898. end
  5899. frame:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT", xOffset, yOffset);
  5900. frame:Hide();
  5901.  
  5902. local width, height;
  5903. if(db.frame) then
  5904. width, height = db.frame.width, db.frame.height;
  5905. end
  5906. if not(width and height) then
  5907. width, height = 630, 492;
  5908. end
  5909. frame:SetWidth(width);
  5910. frame:SetHeight(height);
  5911.  
  5912. local close = CreateFrame("Frame", nil, frame);
  5913. close:SetWidth(17)
  5914. close:SetHeight(40)
  5915. close:SetPoint("TOPRIGHT", -30, 12)
  5916.  
  5917. local closebg = close:CreateTexture(nil, "BACKGROUND")
  5918. closebg:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  5919. closebg:SetTexCoord(0.31, 0.67, 0, 0.63)
  5920. closebg:SetAllPoints(close);
  5921.  
  5922. local closebutton = CreateFrame("BUTTON", nil, close)
  5923. closebutton:SetWidth(30);
  5924. closebutton:SetHeight(30);
  5925. closebutton:SetPoint("CENTER", close, "CENTER", 1, -1);
  5926. closebutton:SetNormalTexture("Interface\\BUTTONS\\UI-Panel-MinimizeButton-Up.blp");
  5927. closebutton:SetPushedTexture("Interface\\BUTTONS\\UI-Panel-MinimizeButton-Down.blp");
  5928. closebutton:SetHighlightTexture("Interface\\BUTTONS\\UI-Panel-MinimizeButton-Highlight.blp");
  5929. closebutton:SetScript("OnClick", WeakAuras.HideOptions);
  5930.  
  5931. local closebg_l = close:CreateTexture(nil, "BACKGROUND")
  5932. closebg_l:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  5933. closebg_l:SetTexCoord(0.235, 0.275, 0, 0.63)
  5934. closebg_l:SetPoint("RIGHT", closebg, "LEFT")
  5935. closebg_l:SetWidth(10)
  5936. closebg_l:SetHeight(40)
  5937.  
  5938. local closebg_r = close:CreateTexture(nil, "BACKGROUND")
  5939. closebg_r:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  5940. closebg_r:SetTexCoord(0.72, 0.76, 0, 0.63)
  5941. closebg_r:SetPoint("LEFT", closebg, "RIGHT")
  5942. closebg_r:SetWidth(10)
  5943. closebg_r:SetHeight(40)
  5944.  
  5945. local import = CreateFrame("Frame", nil, frame);
  5946. import:SetWidth(17)
  5947. import:SetHeight(40)
  5948. import:SetPoint("TOPRIGHT", -100, 12)
  5949. --import:Hide()
  5950.  
  5951. local importbg = import:CreateTexture(nil, "BACKGROUND")
  5952. importbg:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  5953. importbg:SetTexCoord(0.31, 0.67, 0, 0.63)
  5954. importbg:SetAllPoints(import);
  5955.  
  5956. local importbutton = CreateFrame("CheckButton", nil, import, "OptionsCheckButtonTemplate")
  5957. importbutton:SetWidth(30);
  5958. importbutton:SetHeight(30);
  5959. importbutton:SetPoint("CENTER", import, "CENTER", 1, -1);
  5960. importbutton:SetHitRectInsets(0,0,0,0)
  5961. importbutton:SetChecked(db.import_disabled)
  5962.  
  5963. importbutton:SetScript("PostClick", function(self)
  5964. if self:GetChecked() then
  5965. PlaySound("igMainMenuOptionCheckBoxOn")
  5966. db.import_disabled = true
  5967. else
  5968. PlaySound("igMainMenuOptionCheckBoxOff")
  5969. db.import_disabled = nil
  5970. end
  5971. end)
  5972. importbutton:SetScript("OnEnter", function(self)
  5973. GameTooltip:SetOwner(self, "ANCHOR_CURSOR")
  5974. GameTooltip:SetText("Disable Import")
  5975. GameTooltip:AddLine("If this option is enabled, you are no longer able to import auras.", 1, 1, 1)
  5976. GameTooltip:Show()
  5977. end)
  5978. importbutton:SetScript("OnLeave", GameTooltip_Hide)
  5979.  
  5980. local importbg_l = import:CreateTexture(nil, "BACKGROUND")
  5981. importbg_l:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  5982. importbg_l:SetTexCoord(0.235, 0.275, 0, 0.63)
  5983. importbg_l:SetPoint("RIGHT", importbg, "LEFT")
  5984. importbg_l:SetWidth(10)
  5985. importbg_l:SetHeight(40)
  5986.  
  5987. local importbg_r = import:CreateTexture(nil, "BACKGROUND")
  5988. importbg_r:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  5989. importbg_r:SetTexCoord(0.72, 0.76, 0, 0.63)
  5990. importbg_r:SetPoint("LEFT", importbg, "RIGHT")
  5991. importbg_r:SetWidth(10)
  5992. importbg_r:SetHeight(40)
  5993.  
  5994. local titlebg = frame:CreateTexture(nil, "OVERLAY")
  5995. titlebg:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  5996. titlebg:SetTexCoord(0.31, 0.67, 0, 0.63)
  5997. titlebg:SetPoint("TOP", 0, 12)
  5998. titlebg:SetWidth(120)
  5999. titlebg:SetHeight(40)
  6000.  
  6001. local titlebg_l = frame:CreateTexture(nil, "OVERLAY")
  6002. titlebg_l:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  6003. titlebg_l:SetTexCoord(0.21, 0.31, 0, 0.63)
  6004. titlebg_l:SetPoint("RIGHT", titlebg, "LEFT")
  6005. titlebg_l:SetWidth(30)
  6006. titlebg_l:SetHeight(40)
  6007.  
  6008. local titlebg_r = frame:CreateTexture(nil, "OVERLAY")
  6009. titlebg_r:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  6010. titlebg_r:SetTexCoord(0.67, 0.77, 0, 0.63)
  6011. titlebg_r:SetPoint("LEFT", titlebg, "RIGHT")
  6012. titlebg_r:SetWidth(30)
  6013. titlebg_r:SetHeight(40)
  6014.  
  6015. local title = CreateFrame("Frame", nil, frame)
  6016.  
  6017. local function commitWindowChanges()
  6018. local xOffset = frame:GetRight() - GetScreenWidth();
  6019. local yOffset = frame:GetTop() - GetScreenHeight();
  6020. if(title:GetRight() > GetScreenWidth()) then
  6021. xOffset = xOffset + (GetScreenWidth() - title:GetRight());
  6022. elseif(title:GetLeft() < 0) then
  6023. xOffset = xOffset + (0 - title:GetLeft());
  6024. end
  6025. if(title:GetTop() > GetScreenHeight()) then
  6026. yOffset = yOffset + (GetScreenHeight() - title:GetTop());
  6027. elseif(title:GetBottom() < 0) then
  6028. yOffset = yOffset + (0 - title:GetBottom());
  6029. end
  6030. db.frame = db.frame or {};
  6031. db.frame.xOffset = xOffset;
  6032. db.frame.yOffset = yOffset;
  6033. db.frame.width = frame:GetWidth();
  6034. db.frame.height = frame:GetHeight();
  6035. frame:ClearAllPoints();
  6036. frame:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT", xOffset, yOffset);
  6037. end
  6038.  
  6039. title:EnableMouse(true)
  6040. title:SetScript("OnMouseDown", function() frame:StartMoving() end)
  6041. title:SetScript("OnMouseUp", function()
  6042. frame:StopMovingOrSizing();
  6043. commitWindowChanges();
  6044. end);
  6045. title:SetPoint("BOTTOMLEFT", titlebg, "BOTTOMLEFT", -25, 0);
  6046. title:SetPoint("TOPRIGHT", titlebg, "TOPRIGHT", 25, 0);
  6047.  
  6048. local titletext = title:CreateFontString(nil, "OVERLAY", "GameFontNormal")
  6049. titletext:SetPoint("TOP", titlebg, "TOP", 0, -14)
  6050. titletext:SetText(L["WeakAurasOptions"]);
  6051.  
  6052. local sizer_sw = CreateFrame("button",nil,frame);
  6053. sizer_sw:SetPoint("bottomleft",frame,"bottomleft",0,0);
  6054. sizer_sw:SetWidth(25);
  6055. sizer_sw:SetHeight(25);
  6056. sizer_sw:EnableMouse();
  6057. sizer_sw:SetScript("OnMouseDown", function() frame:StartSizing("bottomleft") end);
  6058. sizer_sw:SetScript("OnMouseUp", function()
  6059. frame:StopMovingOrSizing();
  6060. commitWindowChanges();
  6061. end);
  6062. frame.sizer_sw = sizer_sw;
  6063.  
  6064. local sizer_sw_texture = sizer_sw:CreateTexture(nil, "OVERLAY");
  6065. sizer_sw_texture:SetTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Up");
  6066. sizer_sw_texture:SetTexCoord(1, 0, 0, 1);
  6067. sizer_sw_texture:SetPoint("bottomleft", sizer_sw, "bottomleft", 6, 6);
  6068. sizer_sw_texture:SetPoint("topright", sizer_sw, "topright");
  6069. sizer_sw:SetNormalTexture(sizer_sw_texture);
  6070.  
  6071. local sizer_sw_texture_pushed = sizer_sw:CreateTexture(nil, "OVERLAY");
  6072. sizer_sw_texture_pushed:SetTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Down");
  6073. sizer_sw_texture_pushed:SetTexCoord(1, 0, 0, 1);
  6074. sizer_sw_texture_pushed:SetPoint("bottomleft", sizer_sw, "bottomleft", 6, 6);
  6075. sizer_sw_texture_pushed:SetPoint("topright", sizer_sw, "topright");
  6076. sizer_sw:SetPushedTexture(sizer_sw_texture_pushed);
  6077.  
  6078. local sizer_sw_texture_highlight = sizer_sw:CreateTexture(nil, "OVERLAY");
  6079. sizer_sw_texture_highlight:SetTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Highlight");
  6080. sizer_sw_texture_highlight:SetTexCoord(1, 0, 0, 1);
  6081. sizer_sw_texture_highlight:SetPoint("bottomleft", sizer_sw, "bottomleft", 6, 6);
  6082. sizer_sw_texture_highlight:SetPoint("topright", sizer_sw, "topright");
  6083. sizer_sw:SetHighlightTexture(sizer_sw_texture_highlight);
  6084.  
  6085. -- local line1 = sizer_sw:CreateTexture(nil, "BACKGROUND")
  6086. -- line1:SetWidth(14)
  6087. -- line1:SetHeight(14)
  6088. -- line1:SetPoint("bottomleft", 8, 8)
  6089. -- line1:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
  6090. -- local x = 0.1 * 14/17
  6091. -- line1:SetTexCoord(0.05,0.5 - x, 0.5 + x,0.5, 0.05 - x,0.5, 0.05,0.5 + x)
  6092.  
  6093. -- local line2 = sizer_sw:CreateTexture(nil, "BACKGROUND")
  6094. -- line2:SetWidth(8)
  6095. -- line2:SetHeight(8)
  6096. -- line2:SetPoint("bottomleft", 8, 8)
  6097. -- line2:SetTexture("Interface\\Tooltips\\UI-Tooltip-Border")
  6098. -- local x = 0.1 * 8/17
  6099. -- line2:SetTexCoord(0.05,0.5 - x, 0.5 + x,0.5, 0.05 - x,0.5, 0.05,0.5 + x)
  6100. --------------------------------------------------------
  6101.  
  6102.  
  6103. local minimize = CreateFrame("Frame", nil, frame);
  6104. minimize:SetWidth(17)
  6105. minimize:SetHeight(40)
  6106. minimize:SetPoint("TOPRIGHT", -65, 12)
  6107.  
  6108. local minimizebg = minimize:CreateTexture(nil, "BACKGROUND")
  6109. minimizebg:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  6110. minimizebg:SetTexCoord(0.31, 0.67, 0, 0.63)
  6111. minimizebg:SetAllPoints(minimize);
  6112.  
  6113. local minimizebutton = CreateFrame("BUTTON", nil, minimize)
  6114. minimizebutton:SetWidth(30);
  6115. minimizebutton:SetHeight(30);
  6116. minimizebutton:SetPoint("CENTER", minimize, "CENTER", 1, -1);
  6117. minimizebutton:SetNormalTexture("Interface\\BUTTONS\\UI-Panel-CollapseButton-Up.blp");
  6118. minimizebutton:SetPushedTexture("Interface\\BUTTONS\\UI-Panel-CollapseButton-Down.blp");
  6119. minimizebutton:SetHighlightTexture("Interface\\BUTTONS\\UI-Panel-MinimizeButton-Highlight.blp");
  6120. minimizebutton:SetScript("OnClick", function()
  6121. if(frame.minimized) then
  6122. frame.minimized = nil;
  6123. if db.frame then
  6124. if db.frame.height <= 40 then
  6125. db.frame.height = 500
  6126. end
  6127. end
  6128. frame:SetHeight(db.frame and db.frame.height or 500);
  6129. if(frame.window == "default") then
  6130. frame.buttonsContainer.frame:Show();
  6131. frame.container.frame:Show();
  6132. elseif(frame.window == "texture") then
  6133. frame.texturePick.frame:Show();
  6134. elseif(frame.window == "icon") then
  6135. frame.iconPick.frame:Show();
  6136. elseif(frame.window == "model") then
  6137. frame.modelPick.frame:Show();
  6138. elseif(frame.window == "importexport") then
  6139. frame.importexport.frame:Show();
  6140. elseif(frame.window == "texteditor") then
  6141. frame.texteditor.frame:Show();
  6142. end
  6143. minimizebutton:SetNormalTexture("Interface\\BUTTONS\\UI-Panel-CollapseButton-Up.blp");
  6144. minimizebutton:SetPushedTexture("Interface\\BUTTONS\\UI-Panel-CollapseButton-Down.blp");
  6145. else
  6146. frame.minimized = true;
  6147. frame:SetHeight(40);
  6148. frame.buttonsContainer.frame:Hide();
  6149. frame.texturePick.frame:Hide();
  6150. frame.iconPick.frame:Hide();
  6151. frame.modelPick.frame:Hide();
  6152. frame.importexport.frame:Hide();
  6153. frame.texteditor.frame:Hide();
  6154. frame.container.frame:Hide();
  6155. minimizebutton:SetNormalTexture("Interface\\BUTTONS\\UI-Panel-ExpandButton-Up.blp");
  6156. minimizebutton:SetPushedTexture("Interface\\BUTTONS\\UI-Panel-ExpandButton-Down.blp");
  6157. end
  6158. end);
  6159.  
  6160. local minimizebg_l = minimize:CreateTexture(nil, "BACKGROUND")
  6161. minimizebg_l:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  6162. minimizebg_l:SetTexCoord(0.235, 0.275, 0, 0.63)
  6163. minimizebg_l:SetPoint("RIGHT", minimizebg, "LEFT")
  6164. minimizebg_l:SetWidth(10)
  6165. minimizebg_l:SetHeight(40)
  6166.  
  6167. local minimizebg_r = minimize:CreateTexture(nil, "BACKGROUND")
  6168. minimizebg_r:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  6169. minimizebg_r:SetTexCoord(0.72, 0.76, 0, 0.63)
  6170. minimizebg_r:SetPoint("LEFT", minimizebg, "RIGHT")
  6171. minimizebg_r:SetWidth(10)
  6172. minimizebg_r:SetHeight(40)
  6173.  
  6174. local _, _, _, enabled, loadable = GetAddOnInfo("WeakAurasTutorials");
  6175. if(enabled and loadable) then
  6176. local tutorial = CreateFrame("Frame", nil, frame);
  6177. tutorial:SetWidth(17)
  6178. tutorial:SetHeight(40)
  6179. tutorial:SetPoint("TOPRIGHT", -140, 12)
  6180.  
  6181. local tutorialbg = tutorial:CreateTexture(nil, "BACKGROUND")
  6182. tutorialbg:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  6183. tutorialbg:SetTexCoord(0.31, 0.67, 0, 0.63)
  6184. tutorialbg:SetAllPoints(tutorial);
  6185.  
  6186. local tutorialbutton = CreateFrame("BUTTON", nil, tutorial)
  6187. tutorialbutton:SetWidth(30);
  6188. tutorialbutton:SetHeight(30);
  6189. tutorialbutton:SetPoint("CENTER", tutorial, "CENTER", 1, -1);
  6190. tutorialbutton:SetNormalTexture("Interface\\GossipFrame\\DailyActiveQuestIcon");
  6191. tutorialbutton:GetNormalTexture():ClearAllPoints();
  6192. tutorialbutton:GetNormalTexture():SetSize(16, 16);
  6193. tutorialbutton:GetNormalTexture():SetPoint("center", -2, 0);
  6194. tutorialbutton:SetPushedTexture("Interface\\GossipFrame\\DailyActiveQuestIcon");
  6195. tutorialbutton:GetPushedTexture():ClearAllPoints();
  6196. tutorialbutton:GetPushedTexture():SetSize(16, 16);
  6197. tutorialbutton:GetPushedTexture():SetPoint("center", -2, -2);
  6198. tutorialbutton:SetHighlightTexture("Interface\\BUTTONS\\UI-Panel-MinimizeButton-Highlight.blp");
  6199. tutorialbutton:SetScript("OnClick", function()
  6200. if not(IsAddOnLoaded("WeakAurasTutorials")) then
  6201. local loaded, reason = LoadAddOn("WeakAurasTutorials");
  6202. if not(loaded) then
  6203. print("|cff9900FF".."WeakAurasTutorials"..FONT_COLOR_CODE_CLOSE.." could not be loaded: "..RED_FONT_COLOR_CODE.._G["ADDON_"..reason]);
  6204. return;
  6205. end
  6206. end
  6207. WeakAuras.ToggleTutorials();
  6208. end);
  6209.  
  6210. local tutorialbg_l = tutorial:CreateTexture(nil, "BACKGROUND")
  6211. tutorialbg_l:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  6212. tutorialbg_l:SetTexCoord(0.235, 0.275, 0, 0.63)
  6213. tutorialbg_l:SetPoint("RIGHT", tutorialbg, "LEFT")
  6214. tutorialbg_l:SetWidth(10)
  6215. tutorialbg_l:SetHeight(40)
  6216.  
  6217. local tutorialbg_r = tutorial:CreateTexture(nil, "BACKGROUND")
  6218. tutorialbg_r:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  6219. tutorialbg_r:SetTexCoord(0.72, 0.76, 0, 0.63)
  6220. tutorialbg_r:SetPoint("LEFT", tutorialbg, "RIGHT")
  6221. tutorialbg_r:SetWidth(10)
  6222. tutorialbg_r:SetHeight(40)
  6223. end
  6224.  
  6225. local container = AceGUI:Create("InlineGroup");
  6226. container.frame:SetParent(frame);
  6227. container.frame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -17, 12);
  6228. container.frame:SetPoint("TOPLEFT", frame, "TOPRIGHT", -423, -10);
  6229. container.frame:Show();
  6230. container.titletext:Hide();
  6231. frame.container = container;
  6232.  
  6233. local texturePick = AceGUI:Create("InlineGroup");
  6234. texturePick.frame:SetParent(frame);
  6235. texturePick.frame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -17, 42);
  6236. texturePick.frame:SetPoint("TOPLEFT", frame, "TOPLEFT", 17, -10);
  6237. texturePick.frame:Hide();
  6238. texturePick:SetLayout("flow");
  6239. frame.texturePick = texturePick;
  6240. texturePick.children = {};
  6241. texturePick.categories = {};
  6242.  
  6243. local texturePickDropdown = AceGUI:Create("DropdownGroup");
  6244. texturePickDropdown:SetLayout("fill");
  6245. texturePickDropdown.width = "fill";
  6246. texturePickDropdown:SetHeight(390);
  6247. texturePick:SetLayout("fill");
  6248. texturePick:AddChild(texturePickDropdown);
  6249. texturePickDropdown.list = {};
  6250. texturePickDropdown:SetGroupList(texturePickDropdown.list);
  6251.  
  6252. local texturePickScroll = AceGUI:Create("ScrollFrame");
  6253. texturePickScroll:SetWidth(540);
  6254. texturePickScroll:SetLayout("flow");
  6255. texturePickDropdown:AddChild(texturePickScroll);
  6256.  
  6257. local function texturePickGroupSelected(widget, event, uniquevalue)
  6258. texturePickScroll:ReleaseChildren();
  6259. for texturePath, textureName in pairs(texture_types[uniquevalue]) do
  6260. local textureWidget = AceGUI:Create("WeakAurasTextureButton");
  6261. textureWidget:SetTexture(texturePath, textureName);
  6262. textureWidget:SetClick(function()
  6263. texturePick:Pick(texturePath);
  6264. end);
  6265. local d = texturePick.textureData;
  6266. textureWidget:ChangeTexture(d.r, d.g, d.b, d.a, d.rotate, d.discrete_rotation, d.rotation, d.mirror, d.blendMode);
  6267. texturePickScroll:AddChild(textureWidget);
  6268. table.sort(texturePickScroll.children, function(a, b)
  6269. local aPath, bPath = a:GetTexturePath(), b:GetTexturePath();
  6270. local aNum, bNum = tonumber(aPath:match("%d+")), tonumber(bPath:match("%d+"));
  6271. local aNonNumber, bNonNumber = aPath:match("[^%d]+"), bPath:match("[^%d]+")
  6272. if(aNum and bNum and aNonNumber == bNonNumber) then
  6273. return aNum < bNum;
  6274. else
  6275. return aPath < bPath;
  6276. end
  6277. end);
  6278. end
  6279. texturePick:Pick(texturePick.data[texturePick.field]);
  6280. end
  6281.  
  6282. texturePickDropdown:SetCallback("OnGroupSelected", texturePickGroupSelected)
  6283.  
  6284. function texturePick.UpdateList(self)
  6285. wipe(texturePickDropdown.list);
  6286. for categoryName, category in pairs(texture_types) do
  6287. local match = false;
  6288. for texturePath, textureName in pairs(category) do
  6289. if(texturePath == self.data[self.field]) then
  6290. match = true;
  6291. break;
  6292. end
  6293. end
  6294. texturePickDropdown.list[categoryName] = (match and "|cFF80A0FF" or "")..categoryName;
  6295. end
  6296. texturePickDropdown:SetGroupList(texturePickDropdown.list);
  6297. end
  6298.  
  6299. function texturePick.Pick(self, texturePath)
  6300. local pickedwidget;
  6301. for index, widget in ipairs(texturePickScroll.children) do
  6302. widget:ClearPick();
  6303. if(widget:GetTexturePath() == texturePath) then
  6304. pickedwidget = widget;
  6305. end
  6306. end
  6307. if(pickedwidget) then
  6308. pickedwidget:Pick();
  6309. end
  6310. if(self.data.controlledChildren) then
  6311. setAll(self.data, {"region", self.field}, texturePath);
  6312. else
  6313. self.data[self.field] = texturePath;
  6314. end
  6315. if(type(self.data.id) == "string") then
  6316. WeakAuras.Add(self.data);
  6317. WeakAuras.SetIconNames(self.data);
  6318. WeakAuras.SetThumbnail(self.data);
  6319. end
  6320. texturePick:UpdateList();
  6321. local status = texturePickDropdown.status or texturePickDropdown.localstatus
  6322. texturePickDropdown.dropdown:SetText(texturePickDropdown.list[status.selected]);
  6323. end
  6324.  
  6325. function texturePick.Open(self, data, field)
  6326. self.data = data;
  6327. self.field = field;
  6328. if(data.controlledChildren) then
  6329. self.givenPath = {};
  6330. for index, childId in pairs(data.controlledChildren) do
  6331. local childData = WeakAuras.GetData(childId);
  6332. if(childData) then
  6333. self.givenPath[childId] = childData[field];
  6334. end
  6335. end
  6336. local colorAll = getAll(data, {"region", "color"}) or {1, 1, 1, 1};
  6337. self.textureData = {
  6338. r = colorAll[1] or 1,
  6339. g = colorAll[2] or 1,
  6340. b = colorAll[3] or 1,
  6341. a = colorAll[4] or 1,
  6342. rotate = getAll(data, {"region", "rotate"}),
  6343. discrete_rotation = getAll(data, {"region", "discrete_rotation"}) or 0,
  6344. rotation = getAll(data, {"region", "rotation"}) or 0,
  6345. mirror = getAll(data, {"region", "mirror"}),
  6346. blendMode = getAll(data, {"region", "blendMode"}) or "ADD"
  6347. };
  6348. else
  6349. self.givenPath = data[field];
  6350. data.color = data.color or {};
  6351. self.textureData = {
  6352. r = data.color[1] or 1,
  6353. g = data.color[2] or 1,
  6354. b = data.color[3] or 1,
  6355. a = data.color[4] or 1,
  6356. rotate = data.rotate,
  6357. discrete_rotation = data.discrete_rotation or 0,
  6358. rotation = data.rotation or 0,
  6359. mirror = data.mirror,
  6360. blendMode = data.blendMode or "ADD"
  6361. };
  6362. end
  6363. frame.container.frame:Hide();
  6364. frame.buttonsContainer.frame:Hide();
  6365. self.frame:Show();
  6366. frame.window = "texture";
  6367. local picked = false;
  6368. local _, givenPath
  6369. if(type(self.givenPath) == "string") then
  6370. givenPath = self.givenPath;
  6371. else
  6372. _, givenPath = next(self.givenPath);
  6373. end
  6374. WeakAuras.debug(givenPath, 3);
  6375. for categoryName, category in pairs(texture_types) do
  6376. if not(picked) then
  6377. for texturePath, textureName in pairs(category) do
  6378. if(texturePath == givenPath) then
  6379. texturePickDropdown:SetGroup(categoryName);
  6380. self:Pick(givenPath);
  6381. picked = true;
  6382. break;
  6383. end
  6384. end
  6385. end
  6386. end
  6387. if not(picked) then
  6388. for categoryName, category in pairs(texture_types) do
  6389. texturePickDropdown:SetGroup(categoryName);
  6390. break;
  6391. end
  6392. end
  6393. end
  6394.  
  6395. function texturePick.Close()
  6396. texturePick.frame:Hide();
  6397. frame.buttonsContainer.frame:Show();
  6398. frame.container.frame:Show();
  6399. frame.window = "default";
  6400. AceConfigDialog:Open("WeakAuras", container);
  6401. end
  6402.  
  6403. function texturePick.CancelClose()
  6404. if(texturePick.data.controlledChildren) then
  6405. for index, childId in pairs(texturePick.data.controlledChildren) do
  6406. local childData = WeakAuras.GetData(childId);
  6407. if(childData) then
  6408. childData[texturePick.field] = texturePick.givenPath[childId];
  6409. WeakAuras.Add(childData);
  6410. WeakAuras.SetThumbnail(childData);
  6411. WeakAuras.SetIconNames(childData);
  6412. end
  6413. end
  6414. else
  6415. texturePick:Pick(texturePick.givenPath);
  6416. end
  6417. texturePick.Close();
  6418. end
  6419.  
  6420. local texturePickCancel = CreateFrame("Button", nil, texturePick.frame, "UIPanelButtonTemplate")
  6421. texturePickCancel:SetScript("OnClick", texturePick.CancelClose)
  6422. texturePickCancel:SetPoint("BOTTOMRIGHT", -27, -23)
  6423. texturePickCancel:SetHeight(20)
  6424. texturePickCancel:SetWidth(100)
  6425. texturePickCancel:SetText(L["Cancel"])
  6426.  
  6427. local texturePickClose = CreateFrame("Button", nil, texturePick.frame, "UIPanelButtonTemplate")
  6428. texturePickClose:SetScript("OnClick", texturePick.Close)
  6429. texturePickClose:SetPoint("RIGHT", texturePickCancel, "LEFT", -10, 0)
  6430. texturePickClose:SetHeight(20)
  6431. texturePickClose:SetWidth(100)
  6432. texturePickClose:SetText(L["Okay"])
  6433.  
  6434. local iconPick = AceGUI:Create("InlineGroup");
  6435. iconPick.frame:SetParent(frame);
  6436. iconPick.frame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -17, 30); -- 12
  6437. iconPick.frame:SetPoint("TOPLEFT", frame, "TOPLEFT", 17, -10);
  6438. iconPick.frame:Hide();
  6439. iconPick:SetLayout("flow");
  6440. frame.iconPick = iconPick;
  6441.  
  6442. local iconPickScroll = AceGUI:Create("InlineGroup");
  6443. iconPickScroll:SetWidth(540);
  6444. iconPickScroll:SetLayout("flow");
  6445. iconPickScroll.frame:SetParent(iconPick.frame);
  6446. iconPickScroll.frame:SetPoint("BOTTOMLEFT", iconPick.frame, "BOTTOMLEFT", 10, 22); -- 30
  6447. iconPickScroll.frame:SetPoint("TOPRIGHT", iconPick.frame, "TOPRIGHT", -10, -70);
  6448.  
  6449. local function iconPickFill(subname, doSort)
  6450. iconPickScroll:ReleaseChildren();
  6451.  
  6452. local distances = {};
  6453. local names = {};
  6454.  
  6455. subname = tonumber(subname) and GetSpellInfo(tonumber(subname)) or subname;
  6456. subname = subname:lower();
  6457.  
  6458. local num = 0;
  6459. if(subname ~= "") then
  6460. for name, path in pairs(iconCache) do
  6461. local bestDistance = math.huge;
  6462. local bestName;
  6463. if(name:lower():find(subname) or path:lower():find(subname)) then
  6464. if(doSort) then
  6465. local distance = Lev(name, path:sub(17));
  6466. if(distances[path]) then
  6467. if(distance < distances[path]) then
  6468. names[path] = name;
  6469. distances[path] = distance;
  6470. end
  6471. else
  6472. names[path] = name;
  6473. distances[path] = distance;
  6474. num = num + 1;
  6475. end
  6476. else
  6477. if(not names[path]) then
  6478. names[path] = name;
  6479. num = num + 1;
  6480. end
  6481. end
  6482. end
  6483.  
  6484. if(num >= 60) then
  6485. break;
  6486. end
  6487. end
  6488.  
  6489. for path, name in pairs(names) do
  6490. local button = AceGUI:Create("WeakAurasIconButton");
  6491. button:SetName(name);
  6492. button:SetTexture(path);
  6493. button:SetClick(function()
  6494. iconPick:Pick(path);
  6495. end);
  6496. iconPickScroll:AddChild(button);
  6497. end
  6498. end
  6499. end
  6500.  
  6501. local iconPickInput = CreateFrame("EDITBOX", nil, iconPick.frame, "InputBoxTemplate");
  6502. iconPickInput:SetScript("OnTextChanged", function(...) iconPickFill(iconPickInput:GetText(), false); end);
  6503. iconPickInput:SetScript("OnEnterPressed", function(...) iconPickFill(iconPickInput:GetText(), true); end);
  6504. iconPickInput:SetScript("OnEscapePressed", function(...) iconPickInput:SetText(""); iconPickFill(iconPickInput:GetText(), true); end);
  6505. iconPickInput:SetWidth(170);
  6506. iconPickInput:SetHeight(15);
  6507. iconPickInput:SetPoint("TOPRIGHT", iconPick.frame, "TOPRIGHT", -12, -65);
  6508. WeakAuras.iconPickInput = iconPickInput;
  6509.  
  6510. local iconPickInputLabel = iconPickInput:CreateFontString(nil, "OVERLAY", "GameFontNormal");
  6511. iconPickInputLabel:SetText(L["Search"]);
  6512. iconPickInputLabel:SetJustifyH("RIGHT");
  6513. iconPickInputLabel:SetPoint("BOTTOMLEFT", iconPickInput, "TOPLEFT", 0, 5);
  6514.  
  6515. local iconPickIcon = AceGUI:Create("WeakAurasIconButton");
  6516. iconPickIcon.frame:Disable();
  6517. iconPickIcon.frame:SetParent(iconPick.frame);
  6518. iconPickIcon.frame:SetPoint("TOPLEFT", iconPick.frame, "TOPLEFT", 15, -30);
  6519.  
  6520. local iconPickIconLabel = iconPickInput:CreateFontString(nil, "OVERLAY", "GameFontNormalHuge");
  6521. iconPickIconLabel:SetNonSpaceWrap("true");
  6522. iconPickIconLabel:SetJustifyH("LEFT");
  6523. iconPickIconLabel:SetPoint("LEFT", iconPickIcon.frame, "RIGHT", 5, 0);
  6524. iconPickIconLabel:SetPoint("RIGHT", iconPickInput, "LEFT", -50, 0);
  6525.  
  6526. function iconPick.Pick(self, texturePath)
  6527. if(self.data.controlledChildren) then
  6528. for index, childId in pairs(self.data.controlledChildren) do
  6529. local childData = WeakAuras.GetData(childId);
  6530. if(childData) then
  6531. childData[self.field] = texturePath;
  6532. WeakAuras.Add(childData);
  6533. WeakAuras.SetThumbnail(childData);
  6534. WeakAuras.SetIconNames(childData);
  6535. end
  6536. end
  6537. else
  6538. self.data[self.field] = texturePath;
  6539. WeakAuras.Add(self.data);
  6540. WeakAuras.SetThumbnail(self.data);
  6541. WeakAuras.SetIconNames(self.data);
  6542. end
  6543. local success = iconPickIcon:SetTexture(texturePath) and texturePath;
  6544. if(success) then
  6545. iconPickIconLabel:SetText(texturePath:sub(17));
  6546. else
  6547. iconPickIconLabel:SetText();
  6548. end
  6549. end
  6550.  
  6551. function iconPick.Open(self, data, field)
  6552. self.data = data;
  6553. self.field = field;
  6554. if(data.controlledChildren) then
  6555. self.givenPath = {};
  6556. for index, childId in pairs(data.controlledChildren) do
  6557. local childData = WeakAuras.GetData(childId);
  6558. if(childData) then
  6559. self.givenPath[childId] = childData[field];
  6560. end
  6561. end
  6562. else
  6563. self.givenPath = self.data[self.field];
  6564. end
  6565. -- iconPick:Pick(self.givenPath);
  6566. frame.container.frame:Hide();
  6567. frame.buttonsContainer.frame:Hide();
  6568. self.frame:Show();
  6569. frame.window = "icon";
  6570. iconPickInput:SetText("");
  6571. end
  6572.  
  6573. function iconPick.Close()
  6574. iconPick.frame:Hide();
  6575. frame.container.frame:Show();
  6576. frame.buttonsContainer.frame:Show();
  6577. frame.window = "default";
  6578. AceConfigDialog:Open("WeakAuras", container);
  6579. end
  6580.  
  6581. function iconPick.CancelClose()
  6582. if(iconPick.data.controlledChildren) then
  6583. for index, childId in pairs(iconPick.data.controlledChildren) do
  6584. local childData = WeakAuras.GetData(childId);
  6585. if(childData) then
  6586. childData[iconPick.field] = iconPick.givenPath[childId] or childData[iconPick.field];
  6587. WeakAuras.Add(childData);
  6588. WeakAuras.SetThumbnail(childData);
  6589. WeakAuras.SetIconNames(childData);
  6590. end
  6591. end
  6592. else
  6593. iconPick:Pick(iconPick.givenPath);
  6594. end
  6595. iconPick.Close();
  6596. end
  6597.  
  6598. local iconPickCancel = CreateFrame("Button", nil, iconPick.frame, "UIPanelButtonTemplate");
  6599. iconPickCancel:SetScript("OnClick", iconPick.CancelClose);
  6600. iconPickCancel:SetPoint("bottomright", frame, "bottomright", -27, 11);
  6601. iconPickCancel:SetHeight(20);
  6602. iconPickCancel:SetWidth(100);
  6603. iconPickCancel:SetText(L["Cancel"]);
  6604.  
  6605. local iconPickClose = CreateFrame("Button", nil, iconPick.frame, "UIPanelButtonTemplate");
  6606. iconPickClose:SetScript("OnClick", iconPick.Close);
  6607. iconPickClose:SetPoint("RIGHT", iconPickCancel, "LEFT", -10, 0);
  6608. iconPickClose:SetHeight(20);
  6609. iconPickClose:SetWidth(100);
  6610. iconPickClose:SetText(L["Okay"]);
  6611.  
  6612. iconPickScroll.frame:SetPoint("BOTTOM", iconPickClose, "TOP", 0, 10);
  6613.  
  6614. local modelPick = AceGUI:Create("InlineGroup");
  6615. modelPick.frame:SetParent(frame);
  6616. modelPick.frame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -17, 87);
  6617. modelPick.frame:SetPoint("TOPLEFT", frame, "TOPLEFT", 17, -10);
  6618. modelPick.frame:Hide();
  6619. modelPick:SetLayout("flow");
  6620. frame.modelPick = modelPick;
  6621.  
  6622. local modelPickZ = AceGUI:Create("Slider");
  6623. modelPickZ:SetSliderValues(-20, 20, 0.05);
  6624. modelPickZ:SetLabel(L["Z Offset"]);
  6625. modelPickZ.frame:SetParent(modelPick.frame);
  6626. modelPickZ:SetCallback("OnValueChanged", function()
  6627. modelPick:Pick(nil, modelPickZ:GetValue());
  6628. end);
  6629.  
  6630. local modelPickX = AceGUI:Create("Slider");
  6631. modelPickX:SetSliderValues(-20, 20, 0.05);
  6632. modelPickX:SetLabel(L["X Offset"]);
  6633. modelPickX.frame:SetParent(modelPick.frame);
  6634. modelPickX:SetCallback("OnValueChanged", function()
  6635. modelPick:Pick(nil, nil, modelPickX:GetValue());
  6636. end);
  6637.  
  6638. local modelPickY = AceGUI:Create("Slider");
  6639. modelPickY:SetSliderValues(-20, 20, 0.05);
  6640. modelPickY:SetLabel(L["Y Offset"]);
  6641. modelPickY.frame:SetParent(modelPick.frame);
  6642. modelPickY:SetCallback("OnValueChanged", function()
  6643. modelPick:Pick(nil, nil, nil, modelPickY:GetValue());
  6644. end);
  6645.  
  6646. local modelTree = AceGUI:Create("TreeGroup");
  6647. modelPick.modelTree = modelTree;
  6648. modelPick.frame:SetScript("OnUpdate", function()
  6649. local frameWidth = frame:GetWidth();
  6650. local sliderWidth = (frameWidth - 50) / 3;
  6651.  
  6652. modelTree:SetTreeWidth(frameWidth - 370);
  6653.  
  6654. modelPickZ.frame:SetPoint("bottomleft", frame, "bottomleft", 15, 43);
  6655. modelPickZ.frame:SetPoint("bottomright", frame, "bottomleft", 15 + sliderWidth, 43);
  6656.  
  6657. modelPickX.frame:SetPoint("bottomleft", frame, "bottomleft", 25 + sliderWidth, 43);
  6658. modelPickX.frame:SetPoint("bottomright", frame, "bottomleft", 25 + (2 * sliderWidth), 43);
  6659.  
  6660. modelPickY.frame:SetPoint("bottomleft", frame, "bottomleft", 35 + (2 * sliderWidth), 43);
  6661. modelPickY.frame:SetPoint("bottomright", frame, "bottomleft", 35 + (3 * sliderWidth), 43);
  6662. end);
  6663. modelPick:SetLayout("fill");
  6664. modelTree:SetTree(WeakAuras.ModelPaths);
  6665. modelTree:SetCallback("OnGroupSelected", function(self, event, value)
  6666. local path = string.gsub(value, "\001", "/");
  6667. if(string.lower(string.sub(path, -3, -1)) == ".m2") then
  6668. local model_path = path;
  6669. modelPick:Pick(model_path);
  6670. end
  6671. end);
  6672. modelPick:AddChild(modelTree);
  6673.  
  6674. local model = CreateFrame("PlayerModel", nil, modelPick.content);
  6675. model:SetAllPoints(modelTree.content);
  6676. model:SetFrameStrata("FULLSCREEN");
  6677. modelPick.model = model;
  6678.  
  6679. function modelPick.Pick(self, model_path, model_z, model_x, model_y)
  6680. model_path = model_path or self.data.model_path;
  6681. model_z = model_z or self.data.model_z;
  6682. model_x = model_x or self.data.model_x;
  6683. model_y = model_y or self.data.model_y;
  6684.  
  6685. if tonumber(model_path) then
  6686. self.model:SetDisplayInfo(tonumber(model_path))
  6687. else
  6688. self.model:SetModel(model_path);
  6689. end
  6690. self.model:SetPosition(model_z,model_x, model_y);
  6691. self.model:SetFacing(rad(self.data.rotation));
  6692. if(self.data.controlledChildren) then
  6693. for index, childId in pairs(self.data.controlledChildren) do
  6694. local childData = WeakAuras.GetData(childId);
  6695. if(childData) then
  6696. childData.model_path = model_path;
  6697. childData.model_z = model_z;
  6698. childData.model_x = model_x;
  6699. childData.model_y = model_y;
  6700. WeakAuras.Add(childData);
  6701. WeakAuras.SetThumbnail(childData);
  6702. WeakAuras.SetIconNames(childData);
  6703. end
  6704. end
  6705. else
  6706. self.data.model_path = model_path;
  6707. self.data.model_z = model_z;
  6708. self.data.model_x = model_x;
  6709. self.data.model_y = model_y;
  6710. WeakAuras.Add(self.data);
  6711. WeakAuras.SetThumbnail(self.data);
  6712. WeakAuras.SetIconNames(self.data);
  6713. end
  6714. end
  6715.  
  6716. function modelPick.Open(self, data)
  6717. self.data = data;
  6718. if tonumber(data.model_path) then
  6719. model:SetDisplayInfo(tonumber(data.model_path))
  6720. else
  6721. model:SetModel(data.model_path);
  6722. end
  6723. self.model:SetPosition(data.model_z, data.model_x, data.model_y);
  6724. self.model:SetFacing(rad(data.rotation));
  6725.  
  6726. modelPickZ:SetValue(data.model_z);
  6727. modelPickZ.editbox:SetText(("%.2f"):format(data.model_z));
  6728. modelPickX:SetValue(data.model_x);
  6729. modelPickX.editbox:SetText(("%.2f"):format(data.model_x));
  6730. modelPickY:SetValue(data.model_y);
  6731. modelPickY.editbox:SetText(("%.2f"):format(data.model_y));
  6732.  
  6733. if(data.controlledChildren) then
  6734. self.givenModel = {};
  6735. self.givenZ = {};
  6736. self.givenX = {};
  6737. self.givenY = {};
  6738. for index, childId in pairs(data.controlledChildren) do
  6739. local childData = WeakAuras.GetData(childId);
  6740. if(childData) then
  6741. self.givenModel[childId] = childData.model_path;
  6742. self.givenZ[childId] = childData.model_z;
  6743. self.givenX[childId] = childData.model_x;
  6744. self.givenY[childId] = childData.model_y;
  6745. end
  6746. end
  6747. else
  6748. self.givenModel = data.model_path;
  6749. self.givenZ = data.model_z;
  6750. self.givenX = data.model_x;
  6751. self.givenY = data.model_y;
  6752. end
  6753. frame.container.frame:Hide();
  6754. frame.buttonsContainer.frame:Hide();
  6755. self.frame:Show();
  6756. frame.window = "model";
  6757. end
  6758.  
  6759. function modelPick.Close()
  6760. modelPick.frame:Hide();
  6761. frame.container.frame:Show();
  6762. frame.buttonsContainer.frame:Show();
  6763. frame.window = "default";
  6764. AceConfigDialog:Open("WeakAuras", container);
  6765. end
  6766.  
  6767. function modelPick.CancelClose(self)
  6768. if(modelPick.data.controlledChildren) then
  6769. for index, childId in pairs(modelPick.data.controlledChildren) do
  6770. local childData = WeakAuras.GetData(childId);
  6771. if(childData) then
  6772. childData.model_path = modelPick.givenModel[childId];
  6773. childData.model_z = modelPick.givenZ[childId];
  6774. childData.model_x = modelPick.givenX[childId];
  6775. childData.model_y = modelPick.givenY[childId];
  6776. WeakAuras.Add(childData);
  6777. WeakAuras.SetThumbnail(childData);
  6778. WeakAuras.SetIconNames(childData);
  6779. end
  6780. end
  6781. else
  6782. modelPick:Pick(modelPick.givenPath, modelPick.givenZ, modelPick.givenX, modelPick.givenY);
  6783. end
  6784. modelPick.Close();
  6785. end
  6786.  
  6787. local modelPickCancel = CreateFrame("Button", nil, modelPick.frame, "UIPanelButtonTemplate");
  6788. modelPickCancel:SetScript("OnClick", modelPick.CancelClose);
  6789. modelPickCancel:SetPoint("bottomright", frame, "bottomright", -27, 16);
  6790. modelPickCancel:SetHeight(20);
  6791. modelPickCancel:SetWidth(100);
  6792. modelPickCancel:SetText(L["Cancel"]);
  6793.  
  6794. local modelPickClose = CreateFrame("Button", nil, modelPick.frame, "UIPanelButtonTemplate");
  6795. modelPickClose:SetScript("OnClick", modelPick.Close);
  6796. modelPickClose:SetPoint("RIGHT", modelPickCancel, "LEFT", -10, 0);
  6797. modelPickClose:SetHeight(20);
  6798. modelPickClose:SetWidth(100);
  6799. modelPickClose:SetText(L["Okay"]);
  6800.  
  6801. local importexport = AceGUI:Create("InlineGroup");
  6802. importexport.frame:SetParent(frame);
  6803. importexport.frame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -17, 12);
  6804. importexport.frame:SetPoint("TOPLEFT", frame, "TOPLEFT", 17, -10);
  6805. importexport.frame:Hide();
  6806. importexport:SetLayout("fill");
  6807. frame.importexport = importexport;
  6808.  
  6809. local importexportbox = AceGUI:Create("MultiLineEditBox");
  6810. importexportbox:SetWidth(400);
  6811. importexportbox.button:Hide();
  6812. importexport:AddChild(importexportbox);
  6813.  
  6814. local importexportClose = CreateFrame("Button", nil, importexport.frame, "UIPanelButtonTemplate");
  6815. importexportClose:SetScript("OnClick", function() importexport:Close() end);
  6816. importexportClose:SetPoint("BOTTOMRIGHT", -27, 13);
  6817. importexportClose:SetHeight(20);
  6818. importexportClose:SetWidth(100);
  6819. importexportClose:SetText(L["Done"])
  6820.  
  6821. function importexport.Open(self, mode, id)
  6822. if(frame.window == "texture") then
  6823. frame.texturePick:CancelClose();
  6824. elseif(frame.window == "icon") then
  6825. frame.iconPick:CancelClose();
  6826. elseif(frame.window == "model") then
  6827. frame.modelPick:CancelClose();
  6828. end
  6829. frame.container.frame:Hide();
  6830. frame.buttonsContainer.frame:Hide();
  6831. self.frame:Show();
  6832. frame.window = "importexport";
  6833. if(mode == "export" or mode == "table") then
  6834. if(id) then
  6835. local displayStr;
  6836. if(mode == "export") then
  6837. displayStr = WeakAuras.DisplayToString(id, true);
  6838. elseif(mode == "table") then
  6839. displayStr = WeakAuras.DisplayToTableString(id);
  6840. end
  6841. importexportbox.editBox:SetScript("OnEscapePressed", function() importexport:Close(); end);
  6842. importexportbox.editBox:SetScript("OnChar", function() importexportbox:SetText(displayStr); importexportbox.editBox:HighlightText(); end);
  6843. importexportbox.editBox:SetScript("OnMouseUp", function() importexportbox.editBox:HighlightText(); end);
  6844. importexportbox.editBox:SetScript("OnTextChanged", nil);
  6845. importexportbox:SetLabel(id.." - "..#displayStr);
  6846. importexportbox.button:Hide();
  6847. importexportbox:SetText(displayStr);
  6848. importexportbox.editBox:HighlightText();
  6849. importexportbox:SetFocus();
  6850. end
  6851. elseif(mode == "import") then
  6852. importexportbox.editBox:SetScript("OnEscapePressed", function() importexport:Close(); end);
  6853. importexportbox.editBox:SetScript("OnChar", nil);
  6854. importexportbox.editBox:SetScript("OnMouseUp", nil);
  6855. importexportbox.editBox:SetScript("OnTextChanged", function()
  6856. local str = importexportbox:GetText();
  6857. importexportbox:SetLabel(""..#str);
  6858. if(#str > 20) then
  6859. WeakAuras.ImportString(str);
  6860. end
  6861. end);
  6862. importexportbox:SetText("");
  6863. importexportbox:SetLabel("0");
  6864. importexportbox:SetFocus();
  6865. end
  6866. end
  6867.  
  6868. function importexport.Close(self)
  6869. importexportbox:ClearFocus();
  6870. self.frame:Hide();
  6871. frame.container.frame:Show();
  6872. frame.buttonsContainer.frame:Show();
  6873. frame.window = "default";
  6874. end
  6875.  
  6876. local texteditor = AceGUI:Create("InlineGroup");
  6877. texteditor.frame:SetParent(frame);
  6878. texteditor.frame:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -17, 12);
  6879. texteditor.frame:SetPoint("TOPLEFT", frame, "TOPLEFT", 17, -10);
  6880. texteditor.frame:Hide();
  6881. texteditor:SetLayout("fill");
  6882. frame.texteditor = texteditor;
  6883.  
  6884. local SharedMedia = LibStub("LibSharedMedia-3.0");
  6885.  
  6886. local texteditorbox = AceGUI:Create("MultiLineEditBox");
  6887. texteditorbox:SetWidth(400);
  6888. texteditorbox.button:Hide();
  6889. local fontPath = SharedMedia:Fetch("font", "Jack Input");
  6890. if(fontPath) then
  6891. texteditorbox.editBox:SetFont(fontPath, 12);
  6892. end
  6893. texteditor:AddChild(texteditorbox);
  6894.  
  6895. local colorTable = {}
  6896. colorTable[IndentationLib.tokens.TOKEN_SPECIAL] = "|c00ff3333"
  6897. colorTable[IndentationLib.tokens.TOKEN_KEYWORD] = "|c004444ff"
  6898. colorTable[IndentationLib.tokens.TOKEN_COMMENT_SHORT] = "|c0000aa00"
  6899. colorTable[IndentationLib.tokens.TOKEN_COMMENT_LONG] = "|c0000aa00"
  6900. colorTable[IndentationLib.tokens.TOKEN_NUMBER] = "|c00ff9900"
  6901. colorTable[IndentationLib.tokens.TOKEN_STRING] = "|c00999999"
  6902.  
  6903. local tableColor = "|c00ff3333"
  6904. colorTable["..."] = tableColor
  6905. colorTable["{"] = tableColor
  6906. colorTable["}"] = tableColor
  6907. colorTable["["] = tableColor
  6908. colorTable["]"] = tableColor
  6909.  
  6910. local arithmeticColor = "|c00ff3333"
  6911. colorTable["+"] = arithmeticColor
  6912. colorTable["-"] = arithmeticColor
  6913. colorTable["/"] = arithmeticColor
  6914. colorTable["*"] = arithmeticColor
  6915. colorTable[".."] = arithmeticColor
  6916.  
  6917. local logicColor1 = "|c00ff3333"
  6918. colorTable["=="] = logicColor1
  6919. colorTable["<"] = logicColor1
  6920. colorTable["<="] = logicColor1
  6921. colorTable[">"] = logicColor1
  6922. colorTable[">="] = logicColor1
  6923. colorTable["~="] = logicColor1
  6924.  
  6925. local logicColor2 = "|c004444ff"
  6926. colorTable["and"] = logicColor2
  6927. colorTable["or"] = logicColor2
  6928. colorTable["not"] = logicColor2
  6929.  
  6930. colorTable[0] = "|r"
  6931.  
  6932. IndentationLib.enable(texteditorbox.editBox, colorTable, 4);
  6933.  
  6934. local texteditorCancel = CreateFrame("Button", nil, texteditor.frame, "UIPanelButtonTemplate");
  6935. texteditorCancel:SetScript("OnClick", function() texteditor:CancelClose() end);
  6936. texteditorCancel:SetPoint("BOTTOMRIGHT", -27, 13);
  6937. texteditorCancel:SetHeight(20);
  6938. texteditorCancel:SetWidth(100);
  6939. texteditorCancel:SetText(L["Cancel"]);
  6940.  
  6941. local texteditorClose = CreateFrame("Button", nil, texteditor.frame, "UIPanelButtonTemplate");
  6942. texteditorClose:SetScript("OnClick", function() texteditor:Close() end);
  6943. texteditorClose:SetPoint("RIGHT", texteditorCancel, "LEFT", -10, 0)
  6944. texteditorClose:SetHeight(20);
  6945. texteditorClose:SetWidth(100);
  6946. texteditorClose:SetText(L["Done"]);
  6947.  
  6948. local texteditorError = texteditor.frame:CreateFontString(nil, "OVERLAY");
  6949. texteditorError:SetFont("Fonts\\FRIZQT__.TTF", 10)
  6950. texteditorError:SetJustifyH("LEFT");
  6951. texteditorError:SetJustifyV("TOP");
  6952. texteditorError:SetTextColor(1, 0, 0);
  6953. texteditorError:SetPoint("TOPLEFT", texteditorbox.frame, "BOTTOMLEFT", 5, 25);
  6954. texteditorError:SetPoint("BOTTOMRIGHT", texteditorCancel, "TOPRIGHT");
  6955.  
  6956. function texteditor.Open(self, data, path, enclose, addReturn)
  6957. self.data = data;
  6958. self.path = path;
  6959. self.addReturn = addReturn;
  6960. if(frame.window == "texture") then
  6961. frame.texturePick:CancelClose();
  6962. elseif(frame.window == "icon") then
  6963. frame.iconPick:CancelClose();
  6964. end
  6965. frame.container.frame:Hide();
  6966. frame.buttonsContainer.frame:Hide();
  6967. self.frame:Show();
  6968. frame.window = "texteditor";
  6969. local title = (type(data.id) == "string" and data.id or L["Temporary Group"]).." -";
  6970. for index, field in pairs(path) do
  6971. if(type(field) == "number") then
  6972. field = "Trigger "..field+1
  6973. end
  6974. title = title.." "..field:sub(1, 1):upper()..field:sub(2);
  6975. end
  6976. texteditorbox:SetLabel(title);
  6977. texteditorbox.editBox:SetScript("OnEscapePressed", function() texteditor:CancelClose(); end);
  6978. self.oldOnTextChanged = texteditorbox.editBox:GetScript("OnTextChanged");
  6979. texteditorbox.editBox:SetScript("OnTextChanged", function(...)
  6980. local str = texteditorbox.editBox:GetText();
  6981. if not(str) then
  6982. texteditorError:SetText("");
  6983. else
  6984. local _, errorString
  6985. if(enclose) then
  6986. _, errorString = loadstring("return function() "..str.." end");
  6987. else
  6988. _, errorString = loadstring("return "..str);
  6989. end
  6990. texteditorError:SetText(errorString or "");
  6991. end
  6992. self.oldOnTextChanged(...);
  6993. end);
  6994. if(data.controlledChildren) then
  6995. local singleText;
  6996. local sameTexts = true;
  6997. local combinedText = "";
  6998. for index, childId in pairs(data.controlledChildren) do
  6999. local childData = WeakAuras.GetData(childId);
  7000. local text = valueFromPath(childData, path);
  7001. if(addReturn and text and #text > 8) then
  7002. text = text:sub(8);
  7003. end
  7004. if not(singleText) then
  7005. singleText = text;
  7006. else
  7007. if not(singleText == text) then
  7008. sameTexts = false;
  7009. end
  7010. end
  7011. if not(combinedText == "") then
  7012. combinedText = combinedText.."\n\n";
  7013. end
  7014. combinedText = combinedText.."--"..childId.."\n";
  7015. combinedText = combinedText..(text or "");
  7016. end
  7017. if(sameTexts) then
  7018. texteditorbox:SetText(singleText or "");
  7019. else
  7020. texteditorbox:SetText(combinedText);
  7021. end
  7022. else
  7023. if(addReturn) then
  7024. local value = valueFromPath(data, path);
  7025. texteditorbox:SetText(value and #value > 8 and value:sub(8) or "");
  7026. else
  7027. texteditorbox:SetText(valueFromPath(data, path) or "");
  7028. end
  7029. end
  7030. texteditorbox:SetFocus();
  7031. end
  7032.  
  7033. function texteditor.CancelClose(self)
  7034. texteditorbox.editBox:SetScript("OnTextChanged", self.oldOnTextChanged);
  7035. texteditorbox:ClearFocus();
  7036. self.frame:Hide();
  7037. frame.container.frame:Show();
  7038. frame.buttonsContainer.frame:Show();
  7039. frame.window = "default";
  7040. end
  7041.  
  7042. function texteditor.Close(self)
  7043. if(self.data.controlledChildren) then
  7044. for index, childId in pairs(self.data.controlledChildren) do
  7045. local childData = WeakAuras.GetData(childId);
  7046. if(self.addReturn) then
  7047. valueToPath(childData, self.path, "return "..texteditorbox:GetText());
  7048. else
  7049. valueToPath(childData, self.path, texteditorbox:GetText());
  7050. end
  7051. WeakAuras.Add(childData);
  7052. end
  7053. else
  7054. if(self.addReturn) then
  7055. valueToPath(self.data, self.path, "return "..texteditorbox:GetText());
  7056. else
  7057. valueToPath(self.data, self.path, texteditorbox:GetText());
  7058. end
  7059. WeakAuras.Add(self.data);
  7060. end
  7061.  
  7062. texteditorbox.editBox:SetScript("OnTextChanged", self.oldOnTextChanged);
  7063. texteditorbox:ClearFocus();
  7064. self.frame:Hide();
  7065. frame.container.frame:Show();
  7066. frame.buttonsContainer.frame:Show();
  7067. frame.window = "default";
  7068.  
  7069. frame:RefreshPick();
  7070. end
  7071.  
  7072. local buttonsContainer = AceGUI:Create("InlineGroup");
  7073. buttonsContainer:SetWidth(170);
  7074. buttonsContainer.frame:SetParent(frame);
  7075. buttonsContainer.frame:SetPoint("BOTTOMLEFT", frame, "BOTTOMLEFT", 17, 12);
  7076. buttonsContainer.frame:SetPoint("TOP", frame, "TOP", 0, -10);
  7077. buttonsContainer.frame:SetPoint("right", container.frame, "left", -17);
  7078. buttonsContainer.frame:Show();
  7079. frame.buttonsContainer = buttonsContainer;
  7080.  
  7081. local loadProgress = frame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
  7082. loadProgress:SetPoint("TOP", buttonsContainer.frame, "TOP", 0, -4)
  7083. loadProgress:SetText(L["Creating options: "].."0/0");
  7084. frame.loadProgress = loadProgress;
  7085.  
  7086. local filterInput = CreateFrame("editbox", "WeakAurasFilterInput", buttonsContainer.frame, "InputBoxTemplate");
  7087.  
  7088. filterInput:SetAutoFocus(false);
  7089. filterInput:SetScript("OnTextChanged", function(...) WeakAuras.SortDisplayButtons(filterInput:GetText()) end);
  7090. filterInput:SetScript("OnEnterPressed", function(...) filterInput:ClearFocus() end);
  7091. filterInput:SetScript("OnEscapePressed", function(...) filterInput:SetText(""); filterInput:ClearFocus() end);
  7092. filterInput:SetWidth(150);
  7093. filterInput:SetPoint("BOTTOMLEFT", buttonsContainer.frame, "TOPLEFT", 2, -18);
  7094. filterInput:SetPoint("TOPLEFT", buttonsContainer.frame, "TOPLEFT", 2, -2);
  7095. -- Fix from page 181-182 of World of Warcraft Programming: A Guide and Reference for Creating WoW Addon by James Whitehead
  7096. -- @patch 6.0 compatibility quick fix
  7097. if MAX_NUM_TALENTS then
  7098. WeakAurasFilterInputMiddle:ClearAllPoints();
  7099. WeakAurasFilterInputMiddle:SetPoint("BOTTOMLEFT", WeakAurasFilterInputLeft, "BOTTOMRIGHT");
  7100. WeakAurasFilterInputMiddle:SetPoint("TOPRIGHT", WeakAurasFilterInputRight, "TOPLEFT");
  7101. --
  7102. WeakAurasFilterInputLeft:ClearAllPoints();
  7103. WeakAurasFilterInputLeft:SetPoint("bottomleft", filterInput, "bottomleft");
  7104. WeakAurasFilterInputLeft:SetPoint("topleft", filterInput, "topleft");
  7105. WeakAurasFilterInputRight:ClearAllPoints();
  7106. WeakAurasFilterInputRight:SetPoint("bottomright", filterInput, "bottomright");
  7107. WeakAurasFilterInputRight:SetPoint("topright", filterInput, "topright");
  7108. end
  7109. filterInput:SetTextInsets(16, 0, 0, 0);
  7110. local searchIcon = filterInput:CreateTexture(nil, "overlay");
  7111. searchIcon:SetTexture("Interface\\Common\\UI-Searchbox-Icon");
  7112. searchIcon:SetVertexColor(0.6, 0.6, 0.6);
  7113. searchIcon:SetWidth(14);
  7114. searchIcon:SetHeight(14);
  7115. searchIcon:SetPoint("left", filterInput, "left", 3, -1);
  7116. filterInput:SetFont("Fonts\\FRIZQT__.TTF", 10);
  7117. frame.filterInput = filterInput;
  7118. filterInput:Hide();
  7119.  
  7120. local filterInputClear = CreateFrame("BUTTON", nil, buttonsContainer.frame);
  7121. frame.filterInputClear = filterInputClear;
  7122. filterInputClear:SetWidth(12);
  7123. filterInputClear:SetHeight(12);
  7124. filterInputClear:SetPoint("left", filterInput, "right", 0, -1);
  7125. filterInputClear:SetNormalTexture("Interface\\Common\\VoiceChat-Muted");
  7126. filterInputClear:SetHighlightTexture("Interface\\BUTTONS\\UI-Panel-MinimizeButton-Highlight.blp");
  7127. filterInputClear:SetScript("OnClick", function() filterInput:SetText(""); filterInput:ClearFocus() end);
  7128. filterInputClear:Hide();
  7129.  
  7130. local buttonsScroll = AceGUI:Create("ScrollFrame");
  7131. buttonsScroll:SetLayout("ButtonsScrollLayout");
  7132. buttonsScroll.width = "fill";
  7133. buttonsScroll.height = "fill";
  7134. buttonsContainer:SetLayout("fill");
  7135. buttonsContainer:AddChild(buttonsScroll);
  7136. buttonsScroll.DeleteChild = function(self, delete)
  7137. for index, widget in ipairs(buttonsScroll.children) do
  7138. if(widget == delete) then
  7139. tremove(buttonsScroll.children, index);
  7140. end
  7141. end
  7142. delete:OnRelease();
  7143. buttonsScroll:DoLayout();
  7144. end
  7145. frame.buttonsScroll = buttonsScroll;
  7146.  
  7147. function buttonsScroll:GetScrollPos()
  7148. local status = self.status or self.localstatus;
  7149. return status.offset, status.offset + self.scrollframe:GetHeight();
  7150. end
  7151.  
  7152. -- override SetScroll to make childrens visible as needed
  7153. local oldSetScroll = buttonsScroll.SetScroll;
  7154. buttonsScroll.SetScroll = function(self, value)
  7155. if (self:GetScrollPos() ~= value) then
  7156. oldSetScroll(self, value);
  7157. self:DoLayout();
  7158. end
  7159. end
  7160.  
  7161. function buttonsScroll:SetScrollPos(top, bottom)
  7162. local status = self.status or self.localstatus;
  7163. local viewheight = self.scrollframe:GetHeight();
  7164. local height = self.content:GetHeight();
  7165. local move;
  7166.  
  7167. local viewtop = -1 * status.offset;
  7168. local viewbottom = -1 * (status.offset + viewheight);
  7169. if(top > viewtop) then
  7170. move = top - viewtop;
  7171. elseif(bottom < viewbottom) then
  7172. move = bottom - viewbottom;
  7173. else
  7174. move = 0;
  7175. end
  7176.  
  7177. status.offset = status.offset - move;
  7178.  
  7179. self.content:ClearAllPoints();
  7180. self.content:SetPoint("TOPLEFT", 0, status.offset);
  7181. self.content:SetPoint("TOPRIGHT", 0, status.offset);
  7182.  
  7183. status.scrollvalue = status.offset / ((height - viewheight) / 1000.0);
  7184.  
  7185. self:FixScroll();
  7186. end
  7187.  
  7188. local moversizer = CreateFrame("FRAME", nil, frame);
  7189. frame.moversizer = moversizer;
  7190. moversizer:SetBackdrop({
  7191. edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
  7192. edgeSize = 12,
  7193. insets = {left = 0, right = 0, top = 0, bottom = 0}
  7194. });
  7195. moversizer:EnableMouse();
  7196. moversizer:SetFrameStrata("HIGH");
  7197.  
  7198. moversizer.bl = CreateFrame("FRAME", nil, moversizer);
  7199. moversizer.bl:EnableMouse();
  7200. moversizer.bl:SetWidth(16);
  7201. moversizer.bl:SetHeight(16);
  7202. moversizer.bl:SetPoint("BOTTOMLEFT", moversizer, "BOTTOMLEFT");
  7203. moversizer.bl.l = moversizer.bl:CreateTexture(nil, "OVERLAY");
  7204. moversizer.bl.l:SetTexture("Interface\\BUTTONS\\UI-Listbox-Highlight.blp");
  7205. moversizer.bl.l:SetBlendMode("ADD");
  7206. moversizer.bl.l:SetTexCoord(1, 0, 0.5, 0, 1, 1, 0.5, 1);
  7207. moversizer.bl.l:SetPoint("BOTTOMLEFT", moversizer.bl, "BOTTOMLEFT", 3, 3);
  7208. moversizer.bl.l:SetPoint("TOPRIGHT", moversizer.bl, "TOP");
  7209. moversizer.bl.b = moversizer.bl:CreateTexture(nil, "OVERLAY");
  7210. moversizer.bl.b:SetTexture("Interface\\BUTTONS\\UI-Listbox-Highlight.blp");
  7211. moversizer.bl.b:SetBlendMode("ADD");
  7212. moversizer.bl.b:SetTexCoord(0.5, 0, 0.5, 1, 1, 0, 1, 1);
  7213. moversizer.bl.b:SetPoint("BOTTOMLEFT", moversizer.bl.l, "BOTTOMRIGHT");
  7214. moversizer.bl.b:SetPoint("TOPRIGHT", moversizer.bl, "RIGHT");
  7215. moversizer.bl.Highlight = function()
  7216. moversizer.bl.l:Show();
  7217. moversizer.bl.b:Show();
  7218. end
  7219. moversizer.bl.Clear = function()
  7220. moversizer.bl.l:Hide();
  7221. moversizer.bl.b:Hide();
  7222. end
  7223. moversizer.bl.Clear();
  7224.  
  7225. moversizer.br = CreateFrame("FRAME", nil, moversizer);
  7226. moversizer.br:EnableMouse();
  7227. moversizer.br:SetWidth(16);
  7228. moversizer.br:SetHeight(16);
  7229. moversizer.br:SetPoint("BOTTOMRIGHT", moversizer, "BOTTOMRIGHT");
  7230. moversizer.br.r = moversizer.br:CreateTexture(nil, "OVERLAY");
  7231. moversizer.br.r:SetTexture("Interface\\BUTTONS\\UI-Listbox-Highlight.blp");
  7232. moversizer.br.r:SetBlendMode("ADD");
  7233. moversizer.br.r:SetTexCoord(1, 0, 0.5, 0, 1, 1, 0.5, 1);
  7234. moversizer.br.r:SetPoint("BOTTOMRIGHT", moversizer.br, "BOTTOMRIGHT", -3, 3);
  7235. moversizer.br.r:SetPoint("TOPLEFT", moversizer.br, "TOP");
  7236. moversizer.br.b = moversizer.br:CreateTexture(nil, "OVERLAY");
  7237. moversizer.br.b:SetTexture("Interface\\BUTTONS\\UI-Listbox-Highlight.blp");
  7238. moversizer.br.b:SetBlendMode("ADD");
  7239. moversizer.br.b:SetTexCoord(0, 0, 0, 1, 0.5, 0, 0.5, 1);
  7240. moversizer.br.b:SetPoint("BOTTOMRIGHT", moversizer.br.r, "BOTTOMLEFT");
  7241. moversizer.br.b:SetPoint("TOPLEFT", moversizer.br, "LEFT");
  7242. moversizer.br.Highlight = function()
  7243. moversizer.br.r:Show();
  7244. moversizer.br.b:Show();
  7245. end
  7246. moversizer.br.Clear = function()
  7247. moversizer.br.r:Hide();
  7248. moversizer.br.b:Hide();
  7249. end
  7250. moversizer.br.Clear();
  7251.  
  7252. moversizer.tl = CreateFrame("FRAME", nil, moversizer);
  7253. moversizer.tl:EnableMouse();
  7254. moversizer.tl:SetWidth(16);
  7255. moversizer.tl:SetHeight(16);
  7256. moversizer.tl:SetPoint("TOPLEFT", moversizer, "TOPLEFT");
  7257. moversizer.tl.l = moversizer.tl:CreateTexture(nil, "OVERLAY");
  7258. moversizer.tl.l:SetTexture("Interface\\BUTTONS\\UI-Listbox-Highlight.blp");
  7259. moversizer.tl.l:SetBlendMode("ADD");
  7260. moversizer.tl.l:SetTexCoord(0.5, 0, 0, 0, 0.5, 1, 0, 1);
  7261. moversizer.tl.l:SetPoint("TOPLEFT", moversizer.tl, "TOPLEFT", 3, -3);
  7262. moversizer.tl.l:SetPoint("BOTTOMRIGHT", moversizer.tl, "BOTTOM");
  7263. moversizer.tl.t = moversizer.tl:CreateTexture(nil, "OVERLAY");
  7264. moversizer.tl.t:SetTexture("Interface\\BUTTONS\\UI-Listbox-Highlight.blp");
  7265. moversizer.tl.t:SetBlendMode("ADD");
  7266. moversizer.tl.t:SetTexCoord(0.5, 0, 0.5, 1, 1, 0, 1, 1);
  7267. moversizer.tl.t:SetPoint("TOPLEFT", moversizer.tl.l, "TOPRIGHT");
  7268. moversizer.tl.t:SetPoint("BOTTOMRIGHT", moversizer.tl, "RIGHT");
  7269. moversizer.tl.Highlight = function()
  7270. moversizer.tl.l:Show();
  7271. moversizer.tl.t:Show();
  7272. end
  7273. moversizer.tl.Clear = function()
  7274. moversizer.tl.l:Hide();
  7275. moversizer.tl.t:Hide();
  7276. end
  7277. moversizer.tl.Clear();
  7278.  
  7279. moversizer.tr = CreateFrame("FRAME", nil, moversizer);
  7280. moversizer.tr:EnableMouse();
  7281. moversizer.tr:SetWidth(16);
  7282. moversizer.tr:SetHeight(16);
  7283. moversizer.tr:SetPoint("TOPRIGHT", moversizer, "TOPRIGHT");
  7284. moversizer.tr.r = moversizer.tr:CreateTexture(nil, "OVERLAY");
  7285. moversizer.tr.r:SetTexture("Interface\\BUTTONS\\UI-Listbox-Highlight.blp");
  7286. moversizer.tr.r:SetBlendMode("ADD");
  7287. moversizer.tr.r:SetTexCoord(0.5, 0, 0, 0, 0.5, 1, 0, 1);
  7288. moversizer.tr.r:SetPoint("TOPRIGHT", moversizer.tr, "TOPRIGHT", -3, -3);
  7289. moversizer.tr.r:SetPoint("BOTTOMLEFT", moversizer.tr, "BOTTOM");
  7290. moversizer.tr.t = moversizer.tr:CreateTexture(nil, "OVERLAY");
  7291. moversizer.tr.t:SetTexture("Interface\\BUTTONS\\UI-Listbox-Highlight.blp");
  7292. moversizer.tr.t:SetBlendMode("ADD");
  7293. moversizer.tr.t:SetTexCoord(0, 0, 0, 1, 0.5, 0, 0.5, 1);
  7294. moversizer.tr.t:SetPoint("TOPRIGHT", moversizer.tr.r, "TOPLEFT");
  7295. moversizer.tr.t:SetPoint("BOTTOMLEFT", moversizer.tr, "LEFT");
  7296. moversizer.tr.Highlight = function()
  7297. moversizer.tr.r:Show();
  7298. moversizer.tr.t:Show();
  7299. end
  7300. moversizer.tr.Clear = function()
  7301. moversizer.tr.r:Hide();
  7302. moversizer.tr.t:Hide();
  7303. end
  7304. moversizer.tr.Clear();
  7305.  
  7306. moversizer.l = CreateFrame("FRAME", nil, moversizer);
  7307. moversizer.l:EnableMouse();
  7308. moversizer.l:SetWidth(8);
  7309. moversizer.l:SetPoint("TOPLEFT", moversizer.tl, "BOTTOMLEFT");
  7310. moversizer.l:SetPoint("BOTTOMLEFT", moversizer.bl, "TOPLEFT");
  7311. moversizer.l.l = moversizer.l:CreateTexture(nil, "OVERLAY");
  7312. moversizer.l.l:SetTexture("Interface\\BUTTONS\\UI-Listbox-Highlight.blp");
  7313. moversizer.l.l:SetBlendMode("ADD");
  7314. moversizer.l.l:SetTexCoord(1, 0, 0, 0, 1, 1, 0, 1);
  7315. moversizer.l.l:SetPoint("BOTTOMLEFT", moversizer.bl, "BOTTOMLEFT", 3, 3);
  7316. moversizer.l.l:SetPoint("TOPRIGHT", moversizer.tl, "TOP", 0, -3);
  7317. moversizer.l.Highlight = function()
  7318. moversizer.l.l:Show();
  7319. end
  7320. moversizer.l.Clear = function()
  7321. moversizer.l.l:Hide();
  7322. end
  7323. moversizer.l.Clear();
  7324.  
  7325. moversizer.b = CreateFrame("FRAME", nil, moversizer);
  7326. moversizer.b:EnableMouse();
  7327. moversizer.b:SetHeight(8);
  7328. moversizer.b:SetPoint("BOTTOMLEFT", moversizer.bl, "BOTTOMRIGHT");
  7329. moversizer.b:SetPoint("BOTTOMRIGHT", moversizer.br, "BOTTOMLEFT");
  7330. moversizer.b.b = moversizer.b:CreateTexture(nil, "OVERLAY");
  7331. moversizer.b.b:SetTexture("Interface\\BUTTONS\\UI-Listbox-Highlight.blp");
  7332. moversizer.b.b:SetBlendMode("ADD");
  7333. moversizer.b.b:SetTexCoord(1, 0, 0, 0, 1, 1, 0, 1);
  7334. moversizer.b.b:SetPoint("BOTTOMLEFT", moversizer.bl, "BOTTOMLEFT", 3, 3);
  7335. moversizer.b.b:SetPoint("TOPRIGHT", moversizer.br, "RIGHT", -3, 0);
  7336. moversizer.b.Highlight = function()
  7337. moversizer.b.b:Show();
  7338. end
  7339. moversizer.b.Clear = function()
  7340. moversizer.b.b:Hide();
  7341. end
  7342. moversizer.b.Clear();
  7343.  
  7344. moversizer.r = CreateFrame("FRAME", nil, moversizer);
  7345. moversizer.r:EnableMouse();
  7346. moversizer.r:SetWidth(8);
  7347. moversizer.r:SetPoint("BOTTOMRIGHT", moversizer.br, "TOPRIGHT");
  7348. moversizer.r:SetPoint("TOPRIGHT", moversizer.tr, "BOTTOMRIGHT");
  7349. moversizer.r.r = moversizer.r:CreateTexture(nil, "OVERLAY");
  7350. moversizer.r.r:SetTexture("Interface\\BUTTONS\\UI-Listbox-Highlight.blp");
  7351. moversizer.r.r:SetBlendMode("ADD");
  7352. moversizer.r.r:SetPoint("BOTTOMRIGHT", moversizer.br, "BOTTOMRIGHT", -3, 3);
  7353. moversizer.r.r:SetPoint("TOPLEFT", moversizer.tr, "TOP", 0, -3);
  7354. moversizer.r.Highlight = function()
  7355. moversizer.r.r:Show();
  7356. end
  7357. moversizer.r.Clear = function()
  7358. moversizer.r.r:Hide();
  7359. end
  7360. moversizer.r.Clear();
  7361.  
  7362. moversizer.t = CreateFrame("FRAME", nil, moversizer);
  7363. moversizer.t:EnableMouse();
  7364. moversizer.t:SetHeight(8);
  7365. moversizer.t:SetPoint("TOPRIGHT", moversizer.tr, "TOPLEFT");
  7366. moversizer.t:SetPoint("TOPLEFT", moversizer.tl, "TOPRIGHT");
  7367. moversizer.t.t = moversizer.t:CreateTexture(nil, "OVERLAY");
  7368. moversizer.t.t:SetTexture("Interface\\BUTTONS\\UI-Listbox-Highlight.blp");
  7369. moversizer.t.t:SetBlendMode("ADD");
  7370. moversizer.t.t:SetPoint("TOPRIGHT", moversizer.tr, "TOPRIGHT", -3, -3);
  7371. moversizer.t.t:SetPoint("BOTTOMLEFT", moversizer.tl, "LEFT", 3, 0);
  7372. moversizer.t.Highlight = function()
  7373. moversizer.t.t:Show();
  7374. end
  7375. moversizer.t.Clear = function()
  7376. moversizer.t.t:Hide();
  7377. end
  7378. moversizer.t.Clear();
  7379.  
  7380. local mover = CreateFrame("FRAME", nil, moversizer);
  7381. frame.mover = mover;
  7382. mover:EnableMouse();
  7383. mover.moving = {};
  7384. mover.interims = {};
  7385. mover.selfPointIcon = mover:CreateTexture();
  7386. mover.selfPointIcon:SetTexture("Interface\\GLUES\\CharacterSelect\\Glues-AddOn-Icons.blp");
  7387. mover.selfPointIcon:SetWidth(16);
  7388. mover.selfPointIcon:SetHeight(16);
  7389. mover.selfPointIcon:SetTexCoord(0, 0.25, 0, 1);
  7390. mover.anchorPointIcon = mover:CreateTexture();
  7391. mover.anchorPointIcon:SetTexture("Interface\\GLUES\\CharacterSelect\\Glues-AddOn-Icons.blp");
  7392. mover.anchorPointIcon:SetWidth(16);
  7393. mover.anchorPointIcon:SetHeight(16);
  7394. mover.anchorPointIcon:SetTexCoord(0, 0.25, 0, 1);
  7395.  
  7396. local moverText = mover:CreateFontString(nil, "OVERLAY", "GameFontNormal");
  7397. mover.text = moverText;
  7398. moverText:Hide();
  7399.  
  7400. local sizerText = moversizer:CreateFontString(nil, "OVERLAY", "GameFontNormal");
  7401. moversizer.text = sizerText;
  7402. sizerText:Hide();
  7403.  
  7404. moversizer.ScaleCorners = function(self, width, height)
  7405. local limit = math.min(width, height) + 16;
  7406. local size = 16;
  7407. if(limit <= 40) then
  7408. size = limit * (2/5);
  7409. end
  7410. moversizer.bl:SetWidth(size);
  7411. moversizer.bl:SetHeight(size);
  7412. moversizer.br:SetWidth(size);
  7413. moversizer.br:SetHeight(size);
  7414. moversizer.tr:SetWidth(size);
  7415. moversizer.tr:SetHeight(size);
  7416. moversizer.tl:SetWidth(size);
  7417. moversizer.tl:SetHeight(size);
  7418. end
  7419.  
  7420. moversizer.ReAnchor = function(self)
  7421. if(mover.moving.region) then
  7422. self:AnchorPoints(mover.moving.region, mover.moving.data);
  7423. end
  7424. end
  7425.  
  7426. moversizer.AnchorPoints = function(self, region, data)
  7427. local xOff, yOff;
  7428. mover.selfPoint, mover.anchor, mover.anchorPoint, xOff, yOff = region:GetPoint(1);
  7429. mover:ClearAllPoints();
  7430. moversizer:ClearAllPoints();
  7431. if(data.regionType == "group") then
  7432. mover:SetWidth(region.trx - region.blx);
  7433. mover:SetHeight(region.try - region.bly);
  7434. mover:SetPoint(mover.selfPoint, mover.anchor, mover.anchorPoint, xOff + region.blx, yOff + region.bly);
  7435. else
  7436. mover:SetWidth(region:GetWidth());
  7437. mover:SetHeight(region:GetHeight());
  7438. mover:SetPoint(mover.selfPoint, mover.anchor, mover.anchorPoint, xOff, yOff);
  7439. end
  7440. moversizer:SetPoint("BOTTOMLEFT", mover, "BOTTOMLEFT", -8, -8);
  7441. moversizer:SetPoint("TOPRIGHT", mover, "TOPRIGHT", 8, 8);
  7442. moversizer:ScaleCorners(region:GetWidth(), region:GetHeight());
  7443. end
  7444.  
  7445. moversizer.SetToRegion = function(self, region, data)
  7446. mover.moving.region = region;
  7447. mover.moving.data = data;
  7448. local xOff, yOff;
  7449. mover.selfPoint, mover.anchor, mover.anchorPoint, xOff, yOff = region:GetPoint(1);
  7450. mover:ClearAllPoints();
  7451. moversizer:ClearAllPoints();
  7452. if(data.regionType == "group") then
  7453. mover:SetWidth(region.trx - region.blx);
  7454. mover:SetHeight(region.try - region.bly);
  7455. mover:SetPoint(mover.selfPoint, mover.anchor, mover.anchorPoint, xOff + region.blx, yOff + region.bly);
  7456. else
  7457. mover:SetWidth(region:GetWidth());
  7458. mover:SetHeight(region:GetHeight());
  7459. mover:SetPoint(mover.selfPoint, mover.anchor, mover.anchorPoint, xOff, yOff);
  7460. end
  7461. moversizer:SetPoint("BOTTOMLEFT", mover, "BOTTOMLEFT", -8, -8);
  7462. moversizer:SetPoint("TOPRIGHT", mover, "TOPRIGHT", 8, 8);
  7463. moversizer:ScaleCorners(region:GetWidth(), region:GetHeight());
  7464.  
  7465. mover.startMoving = function()
  7466. WeakAuras.CancelAnimation("display", data.id, true, true, true, true, true);
  7467. mover:ClearAllPoints();
  7468. if(data.regionType == "group") then
  7469. mover:SetPoint(mover.selfPoint, region, mover.anchorPoint, region.blx, region.bly);
  7470. else
  7471. mover:SetPoint(mover.selfPoint, region, mover.selfPoint);
  7472. end
  7473. region:StartMoving();
  7474. mover.isMoving = true;
  7475. mover.text:Show();
  7476. end
  7477.  
  7478. mover.doneMoving = function(self)
  7479. region:StopMovingOrSizing();
  7480. mover.isMoving = false;
  7481. mover.text:Hide();
  7482.  
  7483. if(data.xOffset and data.yOffset) then
  7484. local selfX, selfY = mover.selfPointIcon:GetCenter();
  7485. local anchorX, anchorY = mover.anchorPointIcon:GetCenter();
  7486. local dX = selfX - anchorX;
  7487. local dY = selfY - anchorY;
  7488. data.xOffset = dX;
  7489. data.yOffset = dY;
  7490. end
  7491. WeakAuras.Add(data);
  7492. WeakAuras.SetThumbnail(data);
  7493. region:SetPoint(self.selfPoint, self.anchor, self.anchorPoint, data.xOffset, data.yOffset);
  7494. mover.selfPoint, mover.anchor, mover.anchorPoint, xOff, yOff = region:GetPoint(1);
  7495. mover:ClearAllPoints();
  7496. if(data.regionType == "group") then
  7497. mover:SetWidth(region.trx - region.blx);
  7498. mover:SetHeight(region.try - region.bly);
  7499. mover:SetPoint(mover.selfPoint, mover.anchor, mover.anchorPoint, xOff + region.blx, yOff + region.bly);
  7500. else
  7501. mover:SetWidth(region:GetWidth());
  7502. mover:SetHeight(region:GetHeight());
  7503. mover:SetPoint(mover.selfPoint, mover.anchor, mover.anchorPoint, xOff, yOff);
  7504. end
  7505. if(data.parent) then
  7506. local parentData = db.displays[data.parent];
  7507. if(parentData) then
  7508. WeakAuras.Add(parentData);
  7509. WeakAuras.SetThumbnail(parentData);
  7510. end
  7511. end
  7512. AceConfigDialog:Open("WeakAuras", container);
  7513. WeakAuras.Animate("display", data.id, "main", data.animation.main, WeakAuras.regions[data.id].region, false, nil, true);
  7514. end
  7515.  
  7516. if(data.parent and db.displays[data.parent] and db.displays[data.parent].regionType == "dynamicgroup") then
  7517. mover:SetScript("OnMouseDown", nil);
  7518. mover:SetScript("OnMouseUp", nil);
  7519. else
  7520. mover:SetScript("OnMouseDown", mover.startMoving);
  7521. mover:SetScript("OnMouseUp", mover.doneMoving);
  7522. end
  7523.  
  7524. if(region:IsResizable()) then
  7525. moversizer.startSizing = function(point)
  7526. mover.isMoving = true;
  7527. WeakAuras.CancelAnimation("display", data.id, true, true, true, true, true);
  7528. local rSelfPoint, rAnchor, rAnchorPoint, rXOffset, rYOffset = region:GetPoint(1);
  7529. region:StartSizing(point);
  7530. local textpoint, anchorpoint;
  7531. if(point:find("BOTTOM")) then textpoint = "TOP"; anchorpoint = "BOTTOM";
  7532. elseif(point:find("TOP")) then textpoint = "BOTTOM"; anchorpoint = "TOP";
  7533. elseif(point:find("LEFT")) then textpoint = "RIGHT"; anchorpoint = "LEFT";
  7534. elseif(point:find("RIGHT")) then textpoint = "LEFT"; anchorpoint = "RIGHT"; end
  7535. moversizer.text:ClearAllPoints();
  7536. moversizer.text:SetPoint(textpoint, moversizer, anchorpoint);
  7537. moversizer.text:Show();
  7538. mover:SetAllPoints(region);
  7539. moversizer:SetScript("OnUpdate", function()
  7540. moversizer.text:SetText(("(%.2f, %.2f)"):format(region:GetWidth(), region:GetHeight()));
  7541. if(data.width and data.height) then
  7542. data.width = region:GetWidth();
  7543. data.height = region:GetHeight();
  7544. end
  7545. WeakAuras.Add(data);
  7546. region:ClearAllPoints();
  7547. region:SetPoint(rSelfPoint, rAnchor, rAnchorPoint, rXOffset, rYOffset);
  7548. moversizer:ScaleCorners(region:GetWidth(), region:GetHeight());
  7549. AceConfigDialog:Open("WeakAuras", container);
  7550. end);
  7551. end
  7552.  
  7553. moversizer.doneSizing = function()
  7554. mover.isMoving = false;
  7555. region:StopMovingOrSizing();
  7556. WeakAuras.Add(data);
  7557. WeakAuras.SetThumbnail(data);
  7558. if(data.parent) then
  7559. local parentData = db.displays[data.parent];
  7560. WeakAuras.Add(parentData);
  7561. WeakAuras.SetThumbnail(parentData);
  7562. end
  7563. moversizer.text:Hide();
  7564. moversizer:SetScript("OnUpdate", nil);
  7565. mover:ClearAllPoints();
  7566. mover:SetWidth(region:GetWidth());
  7567. mover:SetHeight(region:GetHeight());
  7568. mover:SetPoint(mover.selfPoint, mover.anchor, mover.anchorPoint, xOff, yOff);
  7569. WeakAuras.Animate("display", data.id, "main", data.animation.main, WeakAuras.regions[data.id].region, false, nil, true);
  7570. end
  7571.  
  7572. moversizer.bl:SetScript("OnMouseDown", function() moversizer.startSizing("BOTTOMLEFT") end);
  7573. moversizer.bl:SetScript("OnMouseUp", moversizer.doneSizing);
  7574. moversizer.bl:SetScript("OnEnter", moversizer.bl.Highlight);
  7575. moversizer.bl:SetScript("OnLeave", moversizer.bl.Clear);
  7576. moversizer.b:SetScript("OnMouseDown", function() moversizer.startSizing("BOTTOM") end);
  7577. moversizer.b:SetScript("OnMouseUp", moversizer.doneSizing);
  7578. moversizer.b:SetScript("OnEnter", moversizer.b.Highlight);
  7579. moversizer.b:SetScript("OnLeave", moversizer.b.Clear);
  7580. moversizer.br:SetScript("OnMouseDown", function() moversizer.startSizing("BOTTOMRIGHT") end);
  7581. moversizer.br:SetScript("OnMouseUp", moversizer.doneSizing);
  7582. moversizer.br:SetScript("OnEnter", moversizer.br.Highlight);
  7583. moversizer.br:SetScript("OnLeave", moversizer.br.Clear);
  7584. moversizer.r:SetScript("OnMouseDown", function() moversizer.startSizing("RIGHT") end);
  7585. moversizer.r:SetScript("OnMouseUp", moversizer.doneSizing);
  7586. moversizer.r:SetScript("OnEnter", moversizer.r.Highlight);
  7587. moversizer.r:SetScript("OnLeave", moversizer.r.Clear);
  7588. moversizer.tr:SetScript("OnMouseDown", function() moversizer.startSizing("TOPRIGHT") end);
  7589. moversizer.tr:SetScript("OnMouseUp", moversizer.doneSizing);
  7590. moversizer.tr:SetScript("OnEnter", moversizer.tr.Highlight);
  7591. moversizer.tr:SetScript("OnLeave", moversizer.tr.Clear);
  7592. moversizer.t:SetScript("OnMouseDown", function() moversizer.startSizing("TOP") end);
  7593. moversizer.t:SetScript("OnMouseUp", moversizer.doneSizing);
  7594. moversizer.t:SetScript("OnEnter", moversizer.t.Highlight);
  7595. moversizer.t:SetScript("OnLeave", moversizer.t.Clear);
  7596. moversizer.tl:SetScript("OnMouseDown", function() moversizer.startSizing("TOPLEFT") end);
  7597. moversizer.tl:SetScript("OnMouseUp", moversizer.doneSizing);
  7598. moversizer.tl:SetScript("OnEnter", moversizer.tl.Highlight);
  7599. moversizer.tl:SetScript("OnLeave", moversizer.tl.Clear);
  7600. moversizer.l:SetScript("OnMouseDown", function() moversizer.startSizing("LEFT") end);
  7601. moversizer.l:SetScript("OnMouseUp", moversizer.doneSizing);
  7602. moversizer.l:SetScript("OnEnter", moversizer.l.Highlight);
  7603. moversizer.l:SetScript("OnLeave", moversizer.l.Clear);
  7604.  
  7605. moversizer.bl:Show();
  7606. moversizer.b:Show();
  7607. moversizer.br:Show();
  7608. moversizer.r:Show();
  7609. moversizer.tr:Show();
  7610. moversizer.t:Show();
  7611. moversizer.tl:Show();
  7612. moversizer.l:Show();
  7613. else
  7614. moversizer.bl:Hide();
  7615. moversizer.b:Hide();
  7616. moversizer.br:Hide();
  7617. moversizer.r:Hide();
  7618. moversizer.tr:Hide();
  7619. moversizer.t:Hide();
  7620. moversizer.tl:Hide();
  7621. moversizer.l:Hide();
  7622. end
  7623. moversizer:Show();
  7624. end
  7625.  
  7626. local function EnsureTexture(self, texture)
  7627. if(texture) then
  7628. return texture;
  7629. else
  7630. local ret = self:CreateTexture();
  7631. ret:SetTexture("Interface\\GLUES\\CharacterSelect\\Glues-AddOn-Icons.blp");
  7632. ret:SetWidth(16);
  7633. ret:SetHeight(16);
  7634. ret:SetTexCoord(0, 0.25, 0, 1);
  7635. ret:SetVertexColor(1, 1, 1, 0.25);
  7636. return ret;
  7637. end
  7638. end
  7639.  
  7640. mover:SetScript("OnUpdate", function(self, elaps)
  7641. if(IsShiftKeyDown()) then
  7642. self.goalAlpha = 0.1;
  7643. else
  7644. self.goalAlpha = 1;
  7645. end
  7646.  
  7647. if(self.currentAlpha ~= self.goalAlpha) then
  7648. self.currentAlpha = self.currentAlpha or self:GetAlpha();
  7649. local newAlpha = (self.currentAlpha < self.goalAlpha) and self.currentAlpha + (elaps * 4) or self.currentAlpha - (elaps * 4);
  7650. local newAlpha = (newAlpha > 1 and 1) or (newAlpha < 0.1 and 0.1) or newAlpha;
  7651. mover:SetAlpha(newAlpha);
  7652. moversizer:SetAlpha(newAlpha);
  7653. self.currentAlpha = newAlpha;
  7654. end
  7655.  
  7656. local region = self.moving.region;
  7657. local data = self.moving.data;
  7658. if not(self.isMoving) then
  7659. self.selfPoint, self.anchor, self.anchorPoint = region:GetPoint(1);
  7660. end
  7661. self.selfPointIcon:ClearAllPoints();
  7662. self.selfPointIcon:SetPoint("CENTER", region, self.selfPoint);
  7663. local selfX, selfY = self.selfPointIcon:GetCenter();
  7664. selfX, selfY = selfX or 0, selfY or 0;
  7665. self.anchorPointIcon:ClearAllPoints();
  7666. self.anchorPointIcon:SetPoint("CENTER", self.anchor, self.anchorPoint);
  7667. local anchorX, anchorY = self.anchorPointIcon:GetCenter();
  7668. anchorX, anchorY = anchorX or 0, anchorY or 0;
  7669. if(data.parent and db.displays[data.parent] and db.displays[data.parent].regionType == "dynamicgroup") then
  7670. self.selfPointIcon:Hide();
  7671. self.anchorPointIcon:Hide();
  7672. else
  7673. self.selfPointIcon:Show();
  7674. self.anchorPointIcon:Show();
  7675. end
  7676.  
  7677. local dX = selfX - anchorX;
  7678. local dY = selfY - anchorY;
  7679. local distance = sqrt(dX^2 + dY^2);
  7680. local angle = atan2(dY, dX);
  7681.  
  7682. local numInterim = floor(distance/40);
  7683.  
  7684. for index, texture in pairs(self.interims) do
  7685. texture:Hide();
  7686. end
  7687. for i = 1, numInterim do
  7688. local x = (distance - (i * 40)) * cos(angle);
  7689. local y = (distance - (i * 40)) * sin(angle);
  7690. self.interims[i] = EnsureTexture(self, self.interims[i]);
  7691. self.interims[i]:ClearAllPoints();
  7692. self.interims[i]:SetPoint("CENTER", self.anchorPointIcon, "CENTER", x, y);
  7693. self.interims[i]:Show();
  7694. end
  7695.  
  7696. self.text:SetText(("(%.2f, %.2f)"):format(dX, dY));
  7697. local midx = (distance / 2) * cos(angle);
  7698. local midy = (distance / 2) * sin(angle);
  7699. self.text:SetPoint("CENTER", self.anchorPointIcon, "CENTER", midx, midy);
  7700. if((midx > 0 and (self.text:GetRight() or 0) > (moversizer:GetLeft() or 0)) or (midx < 0 and (self.text:GetLeft() or 0) < (moversizer:GetRight() or 0))) then
  7701. if(midy > 0 and (self.text:GetTop() or 0) > (moversizer:GetBottom() or 0)) then
  7702. midy = midy - ((self.text:GetTop() or 0) - (moversizer:GetBottom() or 0));
  7703. elseif(midy < 0 and (self.text:GetBottom() or 0) < (moversizer:GetTop() or 0)) then
  7704. midy = midy + ((moversizer:GetTop() or 0) - (self.text:GetBottom() or 0));
  7705. end
  7706. end
  7707. self.text:SetPoint("CENTER", self.anchorPointIcon, "CENTER", midx, midy);
  7708. end);
  7709.  
  7710. local newButton = AceGUI:Create("WeakAurasNewHeaderButton");
  7711. newButton:SetText(L["New"]);
  7712. newButton:SetClick(function() frame:PickOption("New") end);
  7713. frame.newButton = newButton;
  7714.  
  7715. local numAddons = 0;
  7716. for addon, addonData in pairs(WeakAuras.addons) do
  7717. numAddons = numAddons + 1;
  7718. end
  7719. if(numAddons > 0) then
  7720. local addonsButton = AceGUI:Create("WeakAurasNewHeaderButton");
  7721. addonsButton:SetText(L["Addons"]);
  7722. addonsButton:SetDescription(L["Manage displays defined by Addons"]);
  7723. addonsButton:SetClick(function() frame:PickOption("Addons") end);
  7724. frame.addonsButton = addonsButton;
  7725. end
  7726.  
  7727. local loadedButton = AceGUI:Create("WeakAurasLoadedHeaderButton");
  7728. loadedButton:SetText(L["Loaded"]);
  7729. loadedButton:Disable();
  7730. loadedButton:EnableExpand();
  7731. if(odb.loadedCollapse) then
  7732. loadedButton:Collapse();
  7733. else
  7734. loadedButton:Expand();
  7735. end
  7736. loadedButton:SetOnExpandCollapse(function()
  7737. if(loadedButton:GetExpanded()) then
  7738. odb.loadedCollapse = nil;
  7739. else
  7740. odb.loadedCollapse = true;
  7741. end
  7742. WeakAuras.SortDisplayButtons()
  7743. end);
  7744. loadedButton:SetExpandDescription(L["Expand all loaded displays"]);
  7745. loadedButton:SetCollapseDescription(L["Collapse all loaded displays"]);
  7746. loadedButton:SetViewClick(function()
  7747. if(loadedButton.view.func() == 2) then
  7748. for id, child in pairs(displayButtons) do
  7749. if(loaded[id] ~= nil) then
  7750. child:PriorityHide(2);
  7751. end
  7752. end
  7753. else
  7754. for id, child in pairs(displayButtons) do
  7755. if(loaded[id] ~= nil) then
  7756. child:PriorityShow(2);
  7757. end
  7758. end
  7759. end
  7760. end);
  7761. loadedButton:SetViewTest(function()
  7762. local none, all = true, true;
  7763. for id, child in pairs(displayButtons) do
  7764. if(loaded[id] ~= nil) then
  7765. if(child:GetVisibility() ~= 2) then
  7766. all = false;
  7767. end
  7768. if(child:GetVisibility() ~= 0) then
  7769. none = false;
  7770. end
  7771. end
  7772. end
  7773. if(all) then
  7774. return 2;
  7775. elseif(none) then
  7776. return 0;
  7777. else
  7778. return 1;
  7779. end
  7780. end);
  7781. loadedButton:SetViewDescription(L["Toggle the visibility of all loaded displays"]);
  7782. frame.loadedButton = loadedButton;
  7783.  
  7784. local unloadedButton = AceGUI:Create("WeakAurasLoadedHeaderButton");
  7785. unloadedButton:SetText(L["Not Loaded"]);
  7786. unloadedButton:Disable();
  7787. unloadedButton:EnableExpand();
  7788. if(odb.unloadedCollapse) then
  7789. unloadedButton:Collapse();
  7790. else
  7791. unloadedButton:Expand();
  7792. end
  7793. unloadedButton:SetOnExpandCollapse(function()
  7794. if(unloadedButton:GetExpanded()) then
  7795. odb.unloadedCollapse = nil;
  7796. else
  7797. odb.unloadedCollapse = true;
  7798. end
  7799. WeakAuras.SortDisplayButtons()
  7800. end);
  7801. unloadedButton:SetExpandDescription(L["Expand all non-loaded displays"]);
  7802. unloadedButton:SetCollapseDescription(L["Collapse all non-loaded displays"]);
  7803. unloadedButton:SetViewClick(function()
  7804. if(unloadedButton.view.func() == 2) then
  7805. for id, child in pairs(displayButtons) do
  7806. if(loaded[id] == nil) then
  7807. child:PriorityHide(2);
  7808. end
  7809. end
  7810. else
  7811. for id, child in pairs(displayButtons) do
  7812. if not(loaded[id] == nil) then
  7813. child:PriorityShow(2);
  7814. end
  7815. end
  7816. end
  7817. end);
  7818. unloadedButton:SetViewTest(function()
  7819. local none, all = true, true;
  7820. for id, child in pairs(displayButtons) do
  7821. if(loaded[id] == nil) then
  7822. if(child:GetVisibility() ~= 2) then
  7823. all = false;
  7824. end
  7825. if(child:GetVisibility() ~= 0) then
  7826. none = false;
  7827. end
  7828. end
  7829. end
  7830. if(all) then
  7831. return 2;
  7832. elseif(none) then
  7833. return 0;
  7834. else
  7835. return 1;
  7836. end
  7837. end);
  7838. unloadedButton:SetViewDescription(L["Toggle the visibility of all non-loaded displays"]);
  7839. frame.unloadedButton = unloadedButton;
  7840.  
  7841. frame.FillOptions = function(self, optionTable)
  7842. AceConfig:RegisterOptionsTable("WeakAuras", optionTable);
  7843. AceConfigDialog:Open("WeakAuras", container);
  7844. container:SetTitle("");
  7845. end
  7846.  
  7847. frame.ClearPicks = function(self, except)
  7848. frame.pickedDisplay = nil;
  7849. frame.pickedOption = nil;
  7850. wipe(tempGroup.controlledChildren);
  7851. for id, button in pairs(displayButtons) do
  7852. button:ClearPick();
  7853. end
  7854. newButton:ClearPick();
  7855. if(frame.addonsButton) then
  7856. frame.addonsButton:ClearPick();
  7857. end
  7858. loadedButton:ClearPick();
  7859. unloadedButton:ClearPick();
  7860. container:ReleaseChildren();
  7861. self.moversizer:Hide();
  7862. end
  7863.  
  7864. frame.PickOption = function(self, option)
  7865. self:ClearPicks();
  7866. self.moversizer:Hide();
  7867. self.pickedOption = option;
  7868. if(option == "New") then
  7869. newButton:Pick();
  7870.  
  7871. local containerScroll = AceGUI:Create("ScrollFrame");
  7872. containerScroll:SetLayout("flow");
  7873. container:SetLayout("fill");
  7874. container:AddChild(containerScroll);
  7875.  
  7876. for regionType, regionData in pairs(regionOptions) do
  7877. local button = AceGUI:Create("WeakAurasNewButton");
  7878. button:SetTitle(regionData.displayName);
  7879. if(type(regionData.icon) == "string") then
  7880. button:SetIcon(regionData.icon);
  7881. elseif(type(regionData.icon) == "function") then
  7882. button:SetIcon(regionData.icon());
  7883. end
  7884. button:SetDescription(regionData.description);
  7885. button:SetClick(function()
  7886. local new_id = "New";
  7887. local num = 2;
  7888. while(db.displays[new_id]) do
  7889. new_id = "New "..num;
  7890. num = num + 1;
  7891. end
  7892.  
  7893. local data = {
  7894. id = new_id,
  7895. regionType = regionType,
  7896. trigger = {
  7897. type = "aura",
  7898. unit = "player",
  7899. debuffType = "HELPFUL"
  7900. },
  7901. load = {}
  7902. };
  7903. WeakAuras.Add(data);
  7904. WeakAuras.NewDisplayButton(data);
  7905. end);
  7906. containerScroll:AddChild(button);
  7907. end
  7908. local importButton = AceGUI:Create("WeakAurasNewButton");
  7909. importButton:SetTitle(L["Import"]);
  7910.  
  7911. local data = {
  7912. outline = false,
  7913. color = {1, 1, 1, 1},
  7914. justify = "CENTER",
  7915. font = "Friz Quadrata TT",
  7916. fontSize = 8,
  7917. displayText = [[
  7918. b4vmErLxtfM
  7919. xu5fDEn1CEn
  7920. vmUmJyZ4hyY
  7921. DtnEnvBEnfz
  7922. EnfzErLxtjx
  7923. zNL2BUrvEWv
  7924. MxtfwDYfMyH
  7925. jNxtLgzEnLt
  7926. LDNx051u25L
  7927. tXmdmY4fDE5]];
  7928. };
  7929.  
  7930. local thumbnail = regionOptions["text"].createThumbnail(UIParent);
  7931. regionOptions["text"].modifyThumbnail(UIParent, thumbnail, data);
  7932. thumbnail.mask:SetPoint("BOTTOMLEFT", thumbnail, "BOTTOMLEFT", 3, 3);
  7933. thumbnail.mask:SetPoint("TOPRIGHT", thumbnail, "TOPRIGHT", -3, -3);
  7934.  
  7935. importButton:SetIcon(thumbnail);
  7936. importButton:SetDescription(L["Import a display from an encoded string"]);
  7937. importButton:SetClick(WeakAuras.ImportFromString);
  7938. containerScroll:AddChild(importButton);
  7939. elseif(option == "Addons") then
  7940. frame.addonsButton:Pick();
  7941.  
  7942. local containerScroll = AceGUI:Create("ScrollFrame");
  7943. containerScroll:SetLayout("AbsoluteList");
  7944. container:SetLayout("fill");
  7945. container:AddChild(containerScroll);
  7946.  
  7947. WeakAuras.CreateImportButtons();
  7948. WeakAuras.SortImportButtons(containerScroll);
  7949. else
  7950. error("An options button other than New or Addons was selected... but there are no other options buttons!");
  7951. end
  7952. end
  7953.  
  7954. frame.PickDisplay = function(self, id)
  7955. self:ClearPicks();
  7956. local data = WeakAuras.GetData(id);
  7957.  
  7958. local function finishPicking()
  7959. displayButtons[id]:Pick();
  7960. self.pickedDisplay = id;
  7961. local data = db.displays[id];
  7962. WeakAuras.ReloadTriggerOptions(data);
  7963. self:FillOptions(displayOptions[id]);
  7964. WeakAuras.regions[id].region:Collapse();
  7965. WeakAuras.regions[id].region:Expand();
  7966. self.moversizer:SetToRegion(WeakAuras.regions[id].region, db.displays[id]);
  7967. local _, _, _, _, yOffset = displayButtons[id].frame:GetPoint(1);
  7968. if (not yOffset) then
  7969. yOffset = displayButtons[id].frame.yOffset;
  7970. end
  7971. self.buttonsScroll:SetScrollPos(yOffset, yOffset - 32);
  7972. if(data.controlledChildren) then
  7973. for index, childId in pairs(data.controlledChildren) do
  7974. displayButtons[childId]:PriorityShow(1);
  7975. end
  7976. end
  7977. end
  7978.  
  7979. local list = {};
  7980. local num = 0;
  7981. if(data.controlledChildren) then
  7982. for index, childId in pairs(data.controlledChildren) do
  7983. if not(displayOptions[childId]) then
  7984. list[childId] = WeakAuras.GetData(childId);
  7985. num = num + 1;
  7986. end
  7987. end
  7988. end
  7989. WeakAuras.EnsureOptions(id);
  7990. if(num > 1) then
  7991. WeakAuras.BuildOptions(list, finishPicking);
  7992. else
  7993. finishPicking();
  7994. end
  7995. end
  7996.  
  7997. frame.CenterOnPicked = function(self)
  7998. if(self.pickedDisplay) then
  7999. local centerId = type(self.pickedDisplay) == "string" and self.pickedDisplay or self.pickedDisplay.controlledChildren[1];
  8000.  
  8001. if(displayButtons[centerId]) then
  8002. local _, _, _, _, yOffset = displayButtons[centerId].frame:GetPoint(1);
  8003. self.buttonsScroll:SetScrollPos(yOffset, yOffset - 32);
  8004. end
  8005. end
  8006. end
  8007.  
  8008. frame.PickDisplayMultiple = function(self, id)
  8009. if not(self.pickedDisplay) then
  8010. self:PickDisplay(id);
  8011. else
  8012. local wasGroup = false;
  8013. if(type(self.pickedDisplay) == "string") then
  8014. if(WeakAuras.GetData(self.pickedDisplay).controlledChildren) then
  8015. wasGroup = true;
  8016. elseif not(WeakAuras.IsDisplayPicked(id)) then
  8017. tinsert(tempGroup.controlledChildren, self.pickedDisplay);
  8018. end
  8019. end
  8020. if(wasGroup) then
  8021. self:PickDisplay(id);
  8022. elseif not(WeakAuras.IsDisplayPicked(id)) then
  8023. self.pickedDisplay = tempGroup;
  8024. WeakAuras.EnsureOptions(id);
  8025. displayButtons[id]:Pick();
  8026. tinsert(tempGroup.controlledChildren, id);
  8027. WeakAuras.ReloadTriggerOptions(tempGroup);
  8028. self:FillOptions(displayOptions[tempGroup.id]);
  8029. end
  8030. end
  8031. end
  8032.  
  8033. frame.RefreshPick = function(self)
  8034. if(type(self.pickedDisplay) == "string") then
  8035. WeakAuras.EnsureOptions(self.pickedDisplay);
  8036. self:FillOptions(displayOptions[self.pickedDisplay]);
  8037. else
  8038. WeakAuras.EnsureOptions(tempGroup.id);
  8039. self:FillOptions(displayOptions[tempGroup.id]);
  8040. end
  8041. end
  8042.  
  8043. frame:SetClampedToScreen(true);
  8044. local w,h = frame:GetSize();
  8045. local left,right,top,bottom = w/2,-w/2,0,h-25
  8046. frame:SetClampRectInsets(left,right,top,bottom);
  8047.  
  8048. return frame;
  8049. end
  8050.  
  8051. function WeakAuras.TextEditor(...)
  8052. frame.texteditor:Open(...);
  8053. end
  8054.  
  8055. function WeakAuras.ExportToString(id)
  8056. frame.importexport:Open("export", id);
  8057. end
  8058.  
  8059. function WeakAuras.ExportToTable(id)
  8060. frame.importexport:Open("table", id);
  8061. end
  8062.  
  8063. function WeakAuras.ImportFromString()
  8064. frame.importexport:Open("import");
  8065. end
  8066.  
  8067. function WeakAuras.CloseImportExport()
  8068. frame.importexport:Close();
  8069. end
  8070.  
  8071. function WeakAuras.ConvertDisplay(data, newType)
  8072. local id = data.id;
  8073. -- thumbnails[id].region:SetScript("OnUpdate", nil);
  8074. thumbnails[id].region:Hide();
  8075. thumbnails[id] = nil;
  8076.  
  8077. WeakAuras.Convert(data, newType);
  8078. displayButtons[id]:SetViewRegion(WeakAuras.regions[id].region);
  8079. displayButtons[id]:Initialize();
  8080. displayOptions[id] = nil;
  8081. WeakAuras.AddOption(id, data);
  8082. frame:FillOptions(displayOptions[id]);
  8083. WeakAuras.UpdateDisplayButton(data);
  8084. frame.mover.moving.region = WeakAuras.regions[id].region;
  8085. WeakAuras.ResetMoverSizer();
  8086. end
  8087.  
  8088. function WeakAuras.NewDisplayButton(data)
  8089. local id = data.id;
  8090. WeakAuras.ScanForLoads();
  8091. WeakAuras.EnsureDisplayButton(db.displays[id]);
  8092. WeakAuras.UpdateDisplayButton(db.displays[id]);
  8093. if(WeakAuras.regions[id].region.SetStacks) then
  8094. WeakAuras.regions[id].region:SetStacks(1);
  8095. end
  8096. frame.buttonsScroll:AddChild(displayButtons[id]);
  8097. WeakAuras.AddOption(id, data);
  8098. WeakAuras.SetIconNames(data);
  8099. WeakAuras.SortDisplayButtons();
  8100.  
  8101. frame:PickDisplay(id);
  8102.  
  8103. displayButtons[id].callbacks.OnRenameClick();
  8104. end
  8105.  
  8106. function WeakAuras.UpdateGroupOrders(data)
  8107. if(data.controlledChildren) then
  8108. local total = #data.controlledChildren;
  8109. for index, id in pairs(data.controlledChildren) do
  8110. local button = WeakAuras.GetDisplayButton(id);
  8111. button:SetGroupOrder(index, total);
  8112. end
  8113. end
  8114. end
  8115.  
  8116. local previousFilter;
  8117. function WeakAuras.SortDisplayButtons(filter, overrideReset)
  8118. local recenter = false;
  8119. filter = filter or (overrideReset and previousFilter or "");
  8120. if(frame.filterInput:GetText() ~= filter) then
  8121. frame.filterInput:SetText(filter);
  8122. end
  8123. if(previousFilter and previousFilter ~= "" and (filter == "" or not filter)) then
  8124. recenter = true;
  8125. end
  8126. previousFilter = filter;
  8127. filter = filter:lower();
  8128.  
  8129. wipe(frame.buttonsScroll.children);
  8130. tinsert(frame.buttonsScroll.children, frame.newButton);
  8131. if(frame.addonsButton) then
  8132. tinsert(frame.buttonsScroll.children, frame.addonsButton);
  8133. end
  8134. tinsert(frame.buttonsScroll.children, frame.loadedButton);
  8135. local numLoaded = 0;
  8136. local to_sort = {};
  8137. local children = {};
  8138. local containsFilter = false;
  8139. for id, child in pairs(displayButtons) do
  8140. containsFilter = false;
  8141. local data = WeakAuras.GetData(id);
  8142. if not(data) then
  8143. print("No data for", id);
  8144. else
  8145. if(filter and data.controlledChildren) then
  8146. for index, childId in pairs(data.controlledChildren) do
  8147. if(childId:lower():find(filter)) then
  8148. containsFilter = true;
  8149. break;
  8150. end
  8151. end
  8152. end
  8153. if(
  8154. frame.loadedButton:GetExpanded()
  8155. and (not filter or id:lower():find(filter) or containsFilter)
  8156. ) then
  8157. child.frame:Show();
  8158. local group = child:GetGroup();
  8159. if(group) then
  8160. if(loaded[group]) then
  8161. if(loaded[id]) then
  8162. child:EnableLoaded();
  8163. else
  8164. child:DisableLoaded();
  8165. end
  8166. children[group] = children[group] or {};
  8167. tinsert(children[group], child);
  8168. end
  8169. else
  8170. if(loaded[id] ~= nil) then
  8171. if(loaded[id]) then
  8172. child:EnableLoaded();
  8173. else
  8174. child:DisableLoaded();
  8175. end
  8176. tinsert(to_sort, child);
  8177. end
  8178. end
  8179. else
  8180. child.frame:Hide();
  8181. end
  8182. end
  8183. end
  8184. table.sort(to_sort, function(a, b) return a:GetTitle() < b:GetTitle() end);
  8185. for _, child in ipairs(to_sort) do
  8186. tinsert(frame.buttonsScroll.children, child);
  8187. local controlledChildren = children[child:GetTitle()];
  8188. if(controlledChildren) then
  8189. table.sort(controlledChildren, function(a, b) return a:GetGroupOrder() < b:GetGroupOrder(); end);
  8190. for _, groupchild in ipairs(controlledChildren) do
  8191. if(child:GetExpanded()) then
  8192. tinsert(frame.buttonsScroll.children, groupchild);
  8193. else
  8194. groupchild.frame:Hide();
  8195. end
  8196. end
  8197. end
  8198. end
  8199.  
  8200. tinsert(frame.buttonsScroll.children, frame.unloadedButton);
  8201. local numUnloaded = 0;
  8202. wipe(to_sort);
  8203. wipe(children);
  8204. for id, child in pairs(displayButtons) do
  8205. containsFilter = false;
  8206. local data = WeakAuras.GetData(id);
  8207. if(filter and data.controlledChildren) then
  8208. for index, childId in pairs(data.controlledChildren) do
  8209. if(childId:lower():find(filter)) then
  8210. containsFilter = true;
  8211. break;
  8212. end
  8213. end
  8214. end
  8215. if(
  8216. frame.unloadedButton:GetExpanded()
  8217. and (not filter or id:lower():find(filter) or containsFilter)
  8218. ) then
  8219. local group = child:GetGroup();
  8220. if(group) then
  8221. if not(loaded[group]) then
  8222. if(loaded[id]) then
  8223. child:EnableLoaded();
  8224. else
  8225. child:DisableLoaded();
  8226. end
  8227. children[group] = children[group] or {};
  8228. tinsert(children[group], child);
  8229. end
  8230. else
  8231. if(loaded[id] == nil) then
  8232. child:DisableLoaded();
  8233. tinsert(to_sort, child);
  8234. end
  8235. end
  8236. else
  8237. child.frame:Hide();
  8238. end
  8239. end
  8240. table.sort(to_sort, function(a, b) return a:GetTitle() < b:GetTitle() end);
  8241. for _, child in ipairs(to_sort) do
  8242. tinsert(frame.buttonsScroll.children, child);
  8243. local controlledChildren = children[child:GetTitle()];
  8244. if(controlledChildren) then
  8245. table.sort(controlledChildren, function(a, b) return a:GetGroupOrder() < b:GetGroupOrder(); end);
  8246. for _, groupchild in ipairs(controlledChildren) do
  8247. if(child:GetExpanded()) then
  8248. tinsert(frame.buttonsScroll.children, groupchild);
  8249. else
  8250. groupchild.frame:Hide();
  8251. end
  8252. end
  8253. end
  8254. end
  8255.  
  8256. frame.buttonsScroll:DoLayout();
  8257. if(recenter) then
  8258. frame:CenterOnPicked();
  8259. end
  8260. end
  8261.  
  8262. WeakAuras.loadFrame:SetScript("OnEvent", function()
  8263. WeakAuras.ScanForLoads();
  8264. if(frame and frame:IsVisible()) then
  8265. WeakAuras.SortDisplayButtons();
  8266. end
  8267. end);
  8268.  
  8269. function WeakAuras.IsPickedMultiple()
  8270. if(frame.pickedDisplay == tempGroup) then
  8271. return true;
  8272. else
  8273. return false;
  8274. end
  8275. end
  8276.  
  8277. function WeakAuras.IsDisplayPicked(id)
  8278. if(frame.pickedDisplay == tempGroup) then
  8279. for index, childId in pairs(tempGroup.controlledChildren) do
  8280. if(id == childId) then
  8281. return true;
  8282. end
  8283. end
  8284. return false;
  8285. else
  8286. return frame.pickedDisplay == id;
  8287. end
  8288. end
  8289.  
  8290. function WeakAuras.PickDisplay(id)
  8291. frame:PickDisplay(id);
  8292. end
  8293.  
  8294. function WeakAuras.PickDisplayMultiple(id)
  8295. frame:PickDisplayMultiple(id);
  8296. end
  8297.  
  8298. function WeakAuras.GetDisplayButton(id)
  8299. if(id and displayButtons[id]) then
  8300. return displayButtons[id];
  8301. end
  8302. end
  8303.  
  8304. function WeakAuras.AddDisplayButton(data)
  8305. WeakAuras.EnsureDisplayButton(data);
  8306. WeakAuras.UpdateDisplayButton(data);
  8307. frame.buttonsScroll:AddChild(displayButtons[data.id]);
  8308. WeakAuras.AddOption(data.id, data);
  8309. WeakAuras.SetIconNames(data);
  8310. if(WeakAuras.regions[data.id] and WeakAuras.regions[data.id].region.SetStacks) then
  8311. WeakAuras.regions[data.id].region:SetStacks(1);
  8312. end
  8313. end
  8314.  
  8315. function WeakAuras.EnsureDisplayButton(data)
  8316. local id = data.id;
  8317. if not(displayButtons[id]) then
  8318. displayButtons[id] = AceGUI:Create("WeakAurasDisplayButton");
  8319. if(displayButtons[id]) then
  8320. displayButtons[id]:SetData(data);
  8321. displayButtons[id]:Initialize();
  8322. else
  8323. print("Error creating button for", id);
  8324. end
  8325. end
  8326. end
  8327.  
  8328. function WeakAuras.SetCopying(data)
  8329. for id, button in pairs(displayButtons) do
  8330. button:SetCopying(data);
  8331. end
  8332. end
  8333.  
  8334. function WeakAuras.SetGrouping(data)
  8335. for id, button in pairs(displayButtons) do
  8336. button:SetGrouping(data);
  8337. end
  8338. end
  8339.  
  8340. function WeakAuras.UpdateDisplayButton(data)
  8341. local id = data.id;
  8342. local button = displayButtons[id];
  8343. if not(button) then
  8344. error("Button for "..id.." was not found!");
  8345. else
  8346. if(regionOptions[data.regionType]) then
  8347. button:SetIcon(WeakAuras.SetThumbnail(data));
  8348. else
  8349. button:SetIcon("Interface\\Icons\\INV_Misc_QuestionMark");
  8350. end
  8351.  
  8352. end
  8353. end
  8354.  
  8355. function WeakAuras.SetThumbnail(data)
  8356. local regionType = data.regionType;
  8357. local regionTypes = WeakAuras.regionTypes;
  8358. if not(regionType) then
  8359. error("Improper arguments to WeakAuras.SetThumbnail - regionType not defined");
  8360. else
  8361. if(regionTypes[regionType]) then
  8362. local id = data.id;
  8363. if not(id) then
  8364. error("Improper arguments to WeakAuras.SetThumbnail - id not defined");
  8365. else
  8366. local button = displayButtons[id];
  8367. local thumbnail, region;
  8368. if(regionOptions[regionType].createThumbnail and regionOptions[regionType].modifyThumbnail) then
  8369. if((not thumbnails[id]) or (not thumbnails[id].region) or thumbnails[id].regionType ~= regionType) then
  8370. thumbnail = regionOptions[regionType].createThumbnail(button.frame, regionTypes[regionType].create);
  8371. thumbnails[id] = {
  8372. regionType = regionType,
  8373. region = thumbnail
  8374. };
  8375. else
  8376. thumbnail = thumbnails[id].region;
  8377. end
  8378. WeakAuras.validate(data, regionTypes[regionType].default);
  8379. regionOptions[regionType].modifyThumbnail(button.frame, thumbnail, data, regionTypes[regionType].modify);
  8380. else
  8381. thumbnail = regionOptions[regionType].icon;
  8382. end
  8383.  
  8384. return thumbnail;
  8385. end
  8386. else
  8387. error("Improper arguments to WeakAuras.SetThumbnail - regionType \""..data.regionType.."\" is not supported and no custom region was supplied");
  8388. end
  8389. end
  8390. end
  8391.  
  8392. function WeakAuras.OpenTexturePick(data, field)
  8393. frame.texturePick:Open(data, field);
  8394. end
  8395.  
  8396. function WeakAuras.OpenIconPick(data, field)
  8397. frame.iconPick:Open(data, field);
  8398. end
  8399.  
  8400. function WeakAuras.OpenModelPick(data, field)
  8401. if not(IsAddOnLoaded("WeakAurasModelPaths")) then
  8402. local loaded, reason = LoadAddOn("WeakAurasModelPaths");
  8403. if not(loaded) then
  8404. print("|cff9900FF".."WeakAurasModelPaths"..FONT_COLOR_CODE_CLOSE.." could not be loaded: "..RED_FONT_COLOR_CODE.._G["ADDON_"..reason]);
  8405. WeakAuras.ModelPaths = {};
  8406. end
  8407. frame.modelPick.modelTree:SetTree(WeakAuras.ModelPaths);
  8408. end
  8409. frame.modelPick:Open(data, field);
  8410. end
  8411.  
  8412. function WeakAuras.ResetMoverSizer()
  8413. if(frame and frame.mover and frame.moversizer and frame.mover.moving.region and frame.mover.moving.data) then
  8414. frame.moversizer:SetToRegion(frame.mover.moving.region, frame.mover.moving.data);
  8415. end
  8416. end
  8417.  
  8418. function WeakAuras.CorrectAuraName(input)
  8419. local spellId = tonumber(input);
  8420. if(spellId) then
  8421. local name, _, icon = GetSpellInfo(spellId);
  8422. if(name) then
  8423. iconCache[name] = icon;
  8424. return name, spellId;
  8425. else
  8426. return "Invalid Spell ID";
  8427. end
  8428. else
  8429. local ret = WeakAuras.BestKeyMatch(input, iconCache);
  8430. if(ret == "") then
  8431. return "No Match Found", nil;
  8432. else
  8433. return ret, nil;
  8434. end
  8435. end
  8436. end
  8437.  
  8438. function WeakAuras.BestKeyMatch(nearkey, table)
  8439. for key, value in pairs(table) do
  8440. if(nearkey:lower() == key:lower()) then
  8441. return key;
  8442. end
  8443. end
  8444. local bestKey = "";
  8445. local bestDistance = math.huge;
  8446. local partialMatches = {};
  8447. for key, value in pairs(table) do
  8448. if(key:lower():find(nearkey:lower())) then
  8449. partialMatches[key] = value;
  8450. end
  8451. end
  8452. for key, value in pairs(partialMatches) do
  8453. local distance = Lev(nearkey, key);
  8454. if(distance < bestDistance) then
  8455. bestKey = key;
  8456. bestDistance = distance;
  8457. end
  8458. end
  8459. return bestKey;
  8460. end
  8461.  
  8462. function WeakAuras.ShowCloneDialog(data)
  8463. if(
  8464. not(
  8465. data.parent
  8466. and WeakAuras.GetData(data.parent)
  8467. and WeakAuras.GetData(data.parent).regionType == "dynamicgroup"
  8468. )
  8469. and not(odb.preventCloneDialog)
  8470. ) then
  8471. StaticPopupDialogs["WEAKAURAS_CLONE_OPTION_ENABLED"] = {
  8472. text = L["Clone option enabled dialog"],
  8473. button1 = L["Yes"],
  8474. button2 = L["No"],
  8475. button3 = L["Never"],
  8476. OnAccept = function()
  8477. local new_id = data.id.." Group";
  8478. local num = 2;
  8479. while(WeakAuras.GetData(new_id)) do
  8480. new_id = "New "..num;
  8481. num = num + 1;
  8482. end
  8483.  
  8484. local parentData = {
  8485. id = new_id,
  8486. regionType = "dynamicgroup",
  8487. trigger = {},
  8488. load = {}
  8489. };
  8490. WeakAuras.Add(parentData);
  8491. WeakAuras.NewDisplayButton(parentData);
  8492.  
  8493. tinsert(parentData.controlledChildren, data.id);
  8494. data.parent = parentData.id;
  8495. WeakAuras.Add(parentData);
  8496. WeakAuras.Add(data);
  8497.  
  8498. local button = WeakAuras.GetDisplayButton(data.id);
  8499. button:SetGroup(parentData.id, true);
  8500. button:SetGroupOrder(1, #parentData.controlledChildren);
  8501.  
  8502. local parentButton = WeakAuras.GetDisplayButton(parentData.id);
  8503. parentButton.callbacks.UpdateExpandButton();
  8504. WeakAuras.UpdateDisplayButton(parentData);
  8505. WeakAuras.ReloadGroupRegionOptions(parentData);
  8506. WeakAuras.SortDisplayButtons();
  8507. parentButton:Expand();
  8508.  
  8509. pickonupdate = data.id;
  8510. end,
  8511. OnCancel = function()
  8512. -- do nothing
  8513. end,
  8514. OnAlt = function()
  8515. odb.preventCloneDialog = true
  8516. end,
  8517. hideOnEscape = true,
  8518. whileDead = true,
  8519. timeout = 0,
  8520. preferredindex = STATICPOPUP_NUMDIALOGS
  8521. };
  8522.  
  8523. StaticPopup_Show("WEAKAURAS_CLONE_OPTION_ENABLED");
  8524. end
  8525. end
  8526.  
  8527. function WeakAuras.ShowSpellIDDialog(trigger, id)
  8528. if not(odb.preventSpellIDDialog) then
  8529. StaticPopupDialogs["WEAKAURAS_SPELLID_CHECK"] = {
  8530. text = L["Spell ID dialog"],
  8531. button1 = L["Yes"],
  8532. button2 = L["No"],
  8533. button3 = L["Never"],
  8534. OnAccept = function()
  8535. trigger.fullscan = true;
  8536. trigger.use_spellId = true;
  8537. trigger.spellId = id;
  8538.  
  8539. AceConfigDialog:Open("WeakAuras", frame.container);
  8540. end,
  8541. OnCancel = function()
  8542. -- do nothing
  8543. end,
  8544. OnAlt = function()
  8545. odb.preventSpellIDDialog = true
  8546. end,
  8547. hideOnEscape = true,
  8548. whileDead = true,
  8549. timeout = 0,
  8550. preferredindex = STATICPOPUP_NUMDIALOGS
  8551. };
  8552.  
  8553. StaticPopup_Show("WEAKAURAS_SPELLID_CHECK");
  8554. end
  8555. end
  8556.  
  8557. do
  8558. local frameChooserFrame;
  8559. local frameChooserBox;
  8560. local oldFocus;
  8561. local oldFocusName;
  8562.  
  8563. function WeakAuras.StartFrameChooser(data, path)
  8564. if not(frameChooserFrame) then
  8565. frameChooserFrame = CreateFrame("frame");
  8566. frameChooserBox = CreateFrame("frame", nil, frameChooserFrame);
  8567. frameChooserBox:SetFrameStrata("TOOLTIP");
  8568. frameChooserBox:SetBackdrop({
  8569. edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
  8570. edgeSize = 12,
  8571. insets = {left = 0, right = 0, top = 0, bottom = 0}
  8572. });
  8573. frameChooserBox:SetBackdropBorderColor(0, 1, 0);
  8574. frameChooserBox:Hide();
  8575. end
  8576. local givenValue = valueFromPath(data, path);
  8577.  
  8578. frameChooserFrame:SetScript("OnUpdate", function()
  8579. if(IsMouseButtonDown("RightButton")) then
  8580. valueToPath(data, path, givenValue);
  8581. AceConfigDialog:Open("WeakAuras", frame.container);
  8582. WeakAuras.StopFrameChooser();
  8583. elseif(IsMouseButtonDown("LeftButton") and oldFocusName) then
  8584. WeakAuras.StopFrameChooser();
  8585. else
  8586. SetCursor("CAST_CURSOR");
  8587.  
  8588. local focus = GetMouseFocus();
  8589. local focusName;
  8590.  
  8591. if(focus) then
  8592. focusName = focus:GetName();
  8593. if(focusName == "WorldFrame" or not focusName) then
  8594. focusName = nil;
  8595. for id, regionData in pairs(WeakAuras.regions) do
  8596. if(regionData.region:IsVisible() and MouseIsOver(regionData.region)) then
  8597. focus = regionData.region;
  8598. focusName = "WeakAuras:"..id;
  8599. end
  8600. end
  8601. end
  8602.  
  8603. if(focus ~= oldFocus) then
  8604. if(focusName) then
  8605. frameChooserBox:SetPoint("bottomleft", focus, "bottomleft", -4, -4);
  8606. frameChooserBox:SetPoint("topright", focus, "topright", 4, 4);
  8607. frameChooserBox:Show();
  8608. end
  8609.  
  8610. if(focusName ~= oldFocusName) then
  8611. valueToPath(data, path, focusName);
  8612. oldFocusName = focusName;
  8613. AceConfigDialog:Open("WeakAuras", frame.container);
  8614. end
  8615. oldFocus = focus;
  8616. end
  8617. end
  8618.  
  8619. if not(focusName) then
  8620. frameChooserBox:Hide();
  8621. end
  8622. end
  8623. end);
  8624. end
  8625.  
  8626. function WeakAuras.StopFrameChooser()
  8627. if(frameChooserFrame) then
  8628. frameChooserFrame:SetScript("OnUpdate", nil);
  8629. frameChooserBox:Hide();
  8630. end
  8631. ResetCursor();
  8632. end
  8633. end
  8634.  
  8635. do
  8636. local importAddonButtons = {};
  8637. local importDisplayButtons = {};
  8638. WeakAuras.importDisplayButtons = importDisplayButtons;
  8639.  
  8640. local collisions = WeakAuras.collisions;
  8641.  
  8642. function WeakAuras.CreateImportButtons()
  8643. wipe(importAddonButtons);
  8644. wipe(importDisplayButtons);
  8645. for addonName, addonData in pairs(WeakAuras.addons) do
  8646. local addonButton = AceGUI:Create("WeakAurasImportButton");
  8647. importAddonButtons[addonName] = addonButton;
  8648. addonButton:SetTitle(addonData.displayName);
  8649. addonButton:SetIcon(addonData.icon);
  8650. addonButton:SetDescription(addonData.description);
  8651. addonButton:SetClick(function()
  8652. if(addonButton.checkbox:GetChecked()) then
  8653. for id, data in pairs(addonData.displays) do
  8654. if not(data.parent) then
  8655. local childButton = importDisplayButtons[id];
  8656. childButton.checkbox:SetChecked(true);
  8657. WeakAuras.EnableAddonDisplay(id);
  8658. end
  8659. end
  8660. for id, data in pairs(addonData.displays) do
  8661. if(data.parent) then
  8662. local childButton = importDisplayButtons[id];
  8663. childButton.checkbox:SetChecked(true);
  8664. WeakAuras.EnableAddonDisplay(id);
  8665. end
  8666. end
  8667. else
  8668. for id, data in pairs(addonData.displays) do
  8669. if not(data.parent) then
  8670. local childButton = importDisplayButtons[id];
  8671. childButton.checkbox:SetChecked(false);
  8672. WeakAuras.DisableAddonDisplay(id);
  8673. end
  8674. end
  8675. for id, data in pairs(addonData.displays) do
  8676. if(data.parent) then
  8677. local childButton = importDisplayButtons[id];
  8678. childButton.checkbox:SetChecked(false);
  8679. WeakAuras.DisableAddonDisplay(id);
  8680. end
  8681. end
  8682. end
  8683. WeakAuras.ResolveCollisions(function()
  8684. for groupId, dataFromAddon in pairs(addonData.displays) do
  8685. if(dataFromAddon.controlledChildren) then
  8686. local data = WeakAuras.GetData(groupId);
  8687. if(data) then
  8688. for index, childId in pairs(data.controlledChildren) do
  8689. local childButton = WeakAuras.GetDisplayButton(childId);
  8690. childButton:SetGroup(groupId, data.regionType == "dynamicgroup");
  8691. childButton:SetGroupOrder(index, #data.controlledChildren);
  8692. end
  8693.  
  8694. local button = WeakAuras.GetDisplayButton(groupId);
  8695. button.callbacks.UpdateExpandButton();
  8696. WeakAuras.UpdateDisplayButton(data);
  8697. WeakAuras.ReloadGroupRegionOptions(data);
  8698. end
  8699. end
  8700. end
  8701.  
  8702. WeakAuras.ScanForLoads();
  8703. WeakAuras.SortDisplayButtons();
  8704. end);
  8705. end);
  8706.  
  8707. local function UpdateAddonChecked()
  8708. local shouldBeChecked = true;
  8709. for id, data in pairs(addonData.displays) do
  8710. if not(WeakAuras.IsDefinedByAddon(id)) then
  8711. shouldBeChecked = false;
  8712. break;
  8713. end
  8714. end
  8715. addonButton.checkbox:SetChecked(shouldBeChecked);
  8716. end
  8717.  
  8718. local numAddonDisplays = 0;
  8719. for id, data in pairs(addonData.displays) do
  8720. if(data.controlledChildren) then
  8721. numAddonDisplays = numAddonDisplays + 1;
  8722. local groupButton = AceGUI:Create("WeakAurasImportButton");
  8723. importDisplayButtons[id] = groupButton;
  8724.  
  8725. groupButton:SetTitle(id);
  8726. groupButton:SetDescription(data.desc);
  8727.  
  8728. local numGroupDisplays = 0;
  8729.  
  8730. local function UpdateGroupChecked()
  8731. local shouldBeChecked = true;
  8732. for index, childId in pairs(data.controlledChildren) do
  8733. if not(WeakAuras.IsDefinedByAddon(childId)) then
  8734. shouldBeChecked = false;
  8735. break;
  8736. end
  8737. end
  8738. groupButton.checkbox:SetChecked(shouldBeChecked);
  8739. UpdateAddonChecked();
  8740. end
  8741.  
  8742. for index, childId in pairs(data.controlledChildren) do
  8743. numGroupDisplays = numGroupDisplays + 1;
  8744. numAddonDisplays = numAddonDisplays + 1;
  8745. local childButton = AceGUI:Create("WeakAurasImportButton");
  8746. importDisplayButtons[childId] = childButton;
  8747.  
  8748. local data = WeakAuras.addons[addonName].displays[childId];
  8749.  
  8750. childButton:SetTitle(childId);
  8751. childButton:SetDescription(data.desc);
  8752. childButton:SetExpandVisible(false);
  8753. childButton:SetLevel(3);
  8754.  
  8755. childButton:SetClick(function()
  8756. if(childButton.checkbox:GetChecked()) then
  8757. WeakAuras.EnableAddonDisplay(childId);
  8758. else
  8759. WeakAuras.DisableAddonDisplay(childId);
  8760. end
  8761. WeakAuras.ResolveCollisions(function()
  8762. WeakAuras.ScanForLoads();
  8763. WeakAuras.SortDisplayButtons();
  8764. UpdateGroupChecked();
  8765. end);
  8766. end);
  8767. childButton.updateChecked = UpdateGroupChecked;
  8768. childButton.checkbox:SetChecked(WeakAuras.IsDefinedByAddon(childId));
  8769. end
  8770.  
  8771. groupButton:SetClick(function()
  8772. if(groupButton.checkbox:GetChecked()) then
  8773. WeakAuras.EnableAddonDisplay(id);
  8774. for index, childId in pairs(data.controlledChildren) do
  8775. local childButton = importDisplayButtons[childId];
  8776. childButton.checkbox:SetChecked(true);
  8777. WeakAuras.EnableAddonDisplay(childId);
  8778. end
  8779. else
  8780. WeakAuras.DisableAddonDisplay(id);
  8781. for index, childId in pairs(data.controlledChildren) do
  8782. local childButton = importDisplayButtons[childId];
  8783. childButton.checkbox:SetChecked(false);
  8784. WeakAuras.DisableAddonDisplay(childId);
  8785. end
  8786. end
  8787. WeakAuras.ResolveCollisions(function()
  8788. local data = WeakAuras.GetData(id);
  8789. if(data) then
  8790. for index, childId in pairs(data.controlledChildren) do
  8791. local childButton = WeakAuras.GetDisplayButton(childId);
  8792. childButton:SetGroup(id, data.regionType == "dynamicgroup");
  8793. childButton:SetGroupOrder(index, #data.controlledChildren);
  8794. end
  8795.  
  8796. local button = WeakAuras.GetDisplayButton(id);
  8797. button.callbacks.UpdateExpandButton();
  8798. WeakAuras.UpdateDisplayButton(data);
  8799. WeakAuras.ReloadGroupRegionOptions(data);
  8800. end
  8801.  
  8802. WeakAuras.ScanForLoads();
  8803. WeakAuras.SortDisplayButtons();
  8804. UpdateAddonChecked();
  8805. end);
  8806. end);
  8807. groupButton.updateChecked = UpdateAddonChecked;
  8808. groupButton:SetExpandVisible(true);
  8809. if(numGroupDisplays > 0) then
  8810. groupButton:EnableExpand();
  8811. groupButton:SetOnExpandCollapse(WeakAuras.SortImportButtons);
  8812. end
  8813. groupButton:SetLevel(2);
  8814. UpdateGroupChecked();
  8815. elseif not(importDisplayButtons[id]) then
  8816. numAddonDisplays = numAddonDisplays + 1;
  8817. local displayButton = AceGUI:Create("WeakAurasImportButton");
  8818. importDisplayButtons[id] = displayButton;
  8819.  
  8820. displayButton:SetTitle(id);
  8821. displayButton:SetDescription(data.desc);
  8822. displayButton:SetExpandVisible(false);
  8823. displayButton:SetLevel(2);
  8824.  
  8825. displayButton:SetClick(function()
  8826. if(displayButton.checkbox:GetChecked()) then
  8827. WeakAuras.EnableAddonDisplay(id);
  8828. else
  8829. WeakAuras.DisableAddonDisplay(id);
  8830. end
  8831. WeakAuras.ResolveCollisions(function()
  8832. WeakAuras.SortDisplayButtons()
  8833. UpdateAddonChecked();
  8834. end);
  8835. end);
  8836. displayButton.updateChecked = UpdateAddonChecked;
  8837. displayButton.checkbox:SetChecked(WeakAuras.IsDefinedByAddon(id));
  8838. end
  8839. end
  8840.  
  8841. addonButton:SetExpandVisible(true);
  8842. if(numAddonDisplays > 0) then
  8843. addonButton:EnableExpand();
  8844. addonButton:SetOnExpandCollapse(WeakAuras.SortImportButtons);
  8845. end
  8846. addonButton:SetLevel(1);
  8847. UpdateAddonChecked();
  8848. end
  8849. end
  8850.  
  8851. local container = nil;
  8852. function WeakAuras.SortImportButtons(newContainer)
  8853. container = newContainer or container;
  8854. wipe(container.children);
  8855. local toSort = {};
  8856. for addon, addonData in pairs(WeakAuras.addons) do
  8857. container:AddChild(importAddonButtons[addon]);
  8858. wipe(toSort);
  8859. for id, data in pairs(addonData.displays) do
  8860. if not(data.parent) then
  8861. tinsert(toSort, id);
  8862. end
  8863. end
  8864. table.sort(toSort, function(a, b) return a < b end);
  8865. for index, id in ipairs(toSort) do
  8866. if(importAddonButtons[addon]:GetExpanded()) then
  8867. importDisplayButtons[id].frame:Show();
  8868. container:AddChild(importDisplayButtons[id]);
  8869. else
  8870. importDisplayButtons[id].frame:Hide();
  8871. end
  8872. if(addonData.displays[id].controlledChildren) then
  8873. for childIndex, childId in pairs(addonData.displays[id].controlledChildren) do
  8874. if(importAddonButtons[addon]:GetExpanded() and importDisplayButtons[id]:GetExpanded()) then
  8875. importDisplayButtons[childId].frame:Show();
  8876. container:AddChild(importDisplayButtons[childId]);
  8877. else
  8878. importDisplayButtons[childId].frame:Hide();
  8879. end
  8880. end
  8881. end
  8882. end
  8883. end
  8884.  
  8885. container:DoLayout();
  8886. end
  8887.  
  8888. function WeakAuras.EnableAddonDisplay(id)
  8889. if not(db.registered[id]) then
  8890. local addon, data;
  8891. for addonName, addonData in pairs(WeakAuras.addons) do
  8892. if(addonData.displays[id]) then
  8893. addon = addonName;
  8894. data = {}
  8895. WeakAuras.DeepCopy(addonData.displays[id], data);
  8896. break;
  8897. end
  8898. end
  8899.  
  8900. if(db.displays[id]) then
  8901. -- ID collision
  8902. collisions[id] = {addon, data};
  8903. else
  8904. db.registered[id] = addon;
  8905. if(data.controlledChildren) then
  8906. wipe(data.controlledChildren);
  8907. end
  8908. WeakAuras.Add(data);
  8909. WeakAuras.SyncParentChildRelationships(true);
  8910. WeakAuras.AddDisplayButton(data);
  8911. end
  8912. end
  8913. end
  8914.  
  8915. -- This function overrides the WeakAuras.CollisionResolved that is defined in WeakAuras.lua, ensuring that sidebar buttons are created properly after collision resolution
  8916. function WeakAuras.CollisionResolved(addon, data, force)
  8917. WeakAuras.EnableAddonDisplay(data.id);
  8918. end
  8919.  
  8920. function WeakAuras.DisableAddonDisplay(id)
  8921. db.registered[id] = false;
  8922. local data = WeakAuras.GetData(id);
  8923. if(data) then
  8924. local parentData;
  8925. if(data.parent) then
  8926. parentData = db.displays[data.parent];
  8927. end
  8928.  
  8929. if(data.controlledChildren) then
  8930. for index, childId in pairs(data.controlledChildren) do
  8931. local childButton = displayButtons[childId];
  8932. if(childButton) then
  8933. childButton:SetGroup();
  8934. end
  8935. local childData = db.displays[childId];
  8936. if(childData) then
  8937. childData.parent = nil;
  8938. end
  8939. end
  8940. end
  8941.  
  8942. WeakAuras.Delete(data);
  8943. WeakAuras.SyncParentChildRelationships(true);
  8944. frame.buttonsScroll:DeleteChild(displayButtons[id]);
  8945. thumbnails[id].region:Hide();
  8946. thumbnails[id] = nil;
  8947. displayButtons[id] = nil;
  8948.  
  8949. if(parentData and parentData.controlledChildren) then
  8950. for index, childId in pairs(parentData.controlledChildren) do
  8951. local childButton = displayButtons[childId];
  8952. if(childButton) then
  8953. childButton:SetGroupOrder(index, #parentData.controlledChildren);
  8954. end
  8955. end
  8956. WeakAuras.Add(parentData);
  8957. WeakAuras.ReloadGroupRegionOptions(parentData);
  8958. WeakAuras.UpdateDisplayButton(parentData);
  8959. end
  8960. end
  8961. end
  8962. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement