SecureStateDriver.lua

SecureStateDriver.lua (9.1.5.40906; unchanged since 9.0.1.36230)
  1. --
  2. -- SecureStateDriverManager
  3. -- Automatically sets states based on macro options for state driver frames
  4. -- Also handled showing/hiding frames based on unit existence (code originally by Tem)
  5. --
  6. -- Register a frame attribute to be set automatically with changes in game state
  7. function RegisterAttributeDriver(frame, attribute, values)
  8. if ( attribute and values and attribute:sub(1, 1) ~= "_" ) then
  9. SecureStateDriverManager:SetAttribute("setframe", frame);
  10. SecureStateDriverManager:SetAttribute("setstate", attribute.." "..values);
  11. end
  12. end
  13. -- Unregister a frame from the state driver manager.
  14. function UnregisterAttributeDriver(frame, attribute)
  15. if ( attribute ) then
  16. SecureStateDriverManager:SetAttribute("setframe", frame);
  17. SecureStateDriverManager:SetAttribute("setstate", attribute);
  18. else
  19. SecureStateDriverManager:SetAttribute("delframe", frame);
  20. end
  21. end
  22. -- Bridge functions for compatibility
  23. function RegisterStateDriver(frame, state, values)
  24. return RegisterAttributeDriver(frame, "state-"..state, values);
  25. end
  26. function UnregisterStateDriver(frame, state)
  27. return UnregisterAttributeDriver(frame, "state-"..state);
  28. end
  29. -- Register a frame to be notified when a unit's existence changes, the
  30. -- unit is obtained from the frame's attributes. If asState is true then
  31. -- notification is via the 'state-unitexists' attribute with values
  32. -- true and false. Otherwise it's via :Show() and :Hide()
  33. function RegisterUnitWatch(frame, asState)
  34. if ( asState ) then
  35. SecureStateDriverManager:SetAttribute("addwatchstate", frame);
  36. else
  37. SecureStateDriverManager:SetAttribute("addwatch", frame);
  38. end
  39. end
  40. -- Unregister a frame from the unit existence monitor.
  41. function UnregisterUnitWatch(frame)
  42. SecureStateDriverManager:SetAttribute("removewatch", frame);
  43. end
  44. --
  45. -- Private implementation
  46. --
  47. local secureAttributeDrivers = {};
  48. local unitExistsWatchers = {};
  49. local unitExistsCache = setmetatable({},
  50. { __index = function(t,k)
  51. local v = UnitExists(k) or false;
  52. t[k] = v;
  53. return v;
  54. end
  55. });
  56. local STATE_DRIVER_UPDATE_THROTTLE = 0.2;
  57. local timer = 0;
  58. local wipe = table.wipe;
  59. -- Check to see if a frame is registered
  60. function UnitWatchRegistered(frame)
  61. return not (unitExistsWatchers[frame] == nil);
  62. end
  63. local function SecureStateDriverManager_UpdateUnitWatch(frame, doState)
  64. local unit = SecureButton_GetUnit(frame);
  65. local exists = (unit and unitExistsCache[unit]);
  66. if ( doState ) then
  67. local attr = exists or false;
  68. if ( frame:GetAttribute("state-unitexists") ~= attr ) then
  69. frame:SetAttribute("state-unitexists", attr);
  70. end
  71. else
  72. if ( exists ) then
  73. frame:Show();
  74. frame:SetAttribute("statehidden", nil);
  75. else
  76. frame:Hide();
  77. frame:SetAttribute("statehidden", true);
  78. end
  79. end
  80. end
  81. local pairs = pairs;
  82. -- consolidate duplicated code for footprint and maintainability
  83. local function resolveDriver(frame, attribute, values)
  84. local newValue = SecureCmdOptionParse(values);
  85. if ( attribute == "state-visibility" ) then
  86. if ( newValue == "show" ) then
  87. frame:Show();
  88. frame:SetAttribute("statehidden", nil);
  89. elseif ( newValue == "hide" ) then
  90. frame:Hide();
  91. frame:SetAttribute("statehidden", true);
  92. end
  93. elseif ( newValue ) then
  94. if ( newValue == 'nil' ) then
  95. newValue = nil;
  96. else
  97. newValue = tonumber(newValue) or newValue;
  98. end
  99. local oldValue = frame:GetAttribute(attribute);
  100. if ( newValue ~= oldValue ) then
  101. frame:SetAttribute(attribute, newValue);
  102. end
  103. end
  104. end
  105. local function SecureStateDriverManager_OnUpdate(self,elapsed)
  106. timer = timer - elapsed;
  107. if ( timer <= 0 ) then
  108. timer = STATE_DRIVER_UPDATE_THROTTLE;
  109. -- Handle state driver updates
  110. for frame,drivers in pairs(secureAttributeDrivers) do
  111. for attribute,values in pairs(drivers) do
  112. resolveDriver(frame, attribute, values);
  113. end
  114. end
  115. -- Handle unit existence changes
  116. wipe(unitExistsCache);
  117. for k in pairs(unitExistsCache) do
  118. unitExistsCache[k] = nil;
  119. end
  120. for frame,doState in pairs(unitExistsWatchers) do
  121. SecureStateDriverManager_UpdateUnitWatch(frame, doState);
  122. end
  123. end
  124. end
  125. local function SecureStateDriverManager_OnEvent(self, event)
  126. timer = 0;
  127. end
  128. local function SecureStateDriverManager_OnAttributeChanged(self, name, value)
  129. if ( not value ) then
  130. return;
  131. end
  132. if ( name == "setframe" ) then
  133. if ( not secureAttributeDrivers[value] ) then
  134. secureAttributeDrivers[value] = {};
  135. end
  136. SecureStateDriverManager:Show();
  137. elseif ( name == "delframe" ) then
  138. secureAttributeDrivers[value] = nil;
  139. elseif ( name == "setstate" ) then
  140. local frame = self:GetAttribute("setframe");
  141. local attribute, values = strmatch(value, "^(%S+)%s*(.*)$");
  142. if ( values == "" ) then
  143. secureAttributeDrivers[frame][attribute] = nil;
  144. else
  145. secureAttributeDrivers[frame][attribute] = values;
  146. resolveDriver(frame, attribute, values);
  147. end
  148. elseif ( name == "addwatch" or name == "addwatchstate" ) then
  149. local doState = (name == "addwatchstate");
  150. unitExistsWatchers[value] = doState;
  151. SecureStateDriverManager:Show();
  152. SecureStateDriverManager_UpdateUnitWatch(value, doState);
  153. elseif ( name == "removewatch" ) then
  154. unitExistsWatchers[value] = nil;
  155. elseif ( name == "updatetime" ) then
  156. STATE_DRIVER_UPDATE_THROTTLE = value;
  157. end
  158. end
  159. SecureStateDriverManager = CreateFrame("Frame", "SecureStateDriverManager", nil, "SecureFrameTemplate");
  160. SecureStateDriverManager:Hide();
  161. SecureStateDriverManager:SetScript("OnUpdate", SecureStateDriverManager_OnUpdate);
  162. SecureStateDriverManager:SetScript("OnEvent", SecureStateDriverManager_OnEvent);
  163. SecureStateDriverManager:SetScript("OnAttributeChanged", SecureStateDriverManager_OnAttributeChanged);
  164. -- Events that trigger early rescans
  165. SecureStateDriverManager:RegisterEvent("MODIFIER_STATE_CHANGED");
  166. SecureStateDriverManager:RegisterEvent("ACTIONBAR_PAGE_CHANGED");
  167. SecureStateDriverManager:RegisterEvent("UPDATE_BONUS_ACTIONBAR");
  168. SecureStateDriverManager:RegisterEvent("PLAYER_ENTERING_WORLD");
  169. SecureStateDriverManager:RegisterEvent("UPDATE_SHAPESHIFT_FORM");
  170. SecureStateDriverManager:RegisterEvent("UPDATE_STEALTH");
  171. SecureStateDriverManager:RegisterEvent("PLAYER_TARGET_CHANGED");
  172. SecureStateDriverManager:RegisterEvent("PLAYER_FOCUS_CHANGED");
  173. SecureStateDriverManager:RegisterEvent("PLAYER_REGEN_DISABLED");
  174. SecureStateDriverManager:RegisterEvent("PLAYER_REGEN_ENABLED");
  175. SecureStateDriverManager:RegisterEvent("UNIT_PET");
  176. SecureStateDriverManager:RegisterEvent("GROUP_ROSTER_UPDATE");
  177. -- Deliberately ignoring mouseover and others' target changes because they change so much